J'ai une structure de données récursive dans mon projet :
(il s'agit d'un exemple simplifié)
pub trait Condition {
fn validate(&self, s: &str) -> bool;
}
pub struct Equal {
ref_val: String,
}
impl Condition for Equal {
fn validate(&self, s: &str) -> bool { self.ref_val == s }
}
pub struct And<A, B> where A: Condition + ?Sized, B: Condition + ?Sized {
left: Box<A>,
right: Box<B>,
}
impl<A, B> Condition for And<A, B> where A: Condition + ?Sized, B: Condition + ?Sized {
fn validate(&self, s: &str) -> bool { self.left.validate(s) && self.right.validate(s) }
}
et je veux sérialiser et dé-sérialiser le trait de condition (en utilisant la fonction serde
) eg. :
fn main() {
let c = And {
left: Box::new(Equal{ ref_val: "goofy".to_string() }),
right: Box::new(Equal{ ref_val: "goofy".to_string() }),
};
let s = serde_json::to_string(&c).unwrap();
let d: Box<dyn Condition> = serde_json::from_string(&s).unwrap();
}
Parce que serde
ne peut pas désérialiser les traits dyn en sortie de boîte, j'ai marqué le balisage sérialisé, par exemple :
#[derive(PartialEq, Debug, Serialize)]
#[serde(tag="type")]
pub struct Equal {
ref_val: String,
}
et essayer de mettre en œuvre un Deserializer
et un Vistor
para Box<dyn Condition>
Étant donné que je suis nouveau dans Rust et que l'implémentation d'un Deserializer et d'un Visitor n'est pas si simple avec la documentation donnée, je me demande si quelqu'un a une idée pour résoudre mon problème avec une approche plus facile ?
J'ai parcouru la documentation de Serde et j'ai cherché une solution sur les sites/forums techniques. J'ai essayé étiquette d'identification mais il ne prend pas en charge les types génériques
UPDATE :
Pour être plus précis : la sérialisation fonctionne bien, c'est-à-dire que serde peut sérialiser n'importe quel objet concret du trait Condition, mais pour désérialiser une Condition, l'information de type concret doit être fournie. Mais cette information de type n'est pas disponible au moment de la compilation. Je suis en train d'écrire un service web où les clients peuvent télécharger des règles pour la correspondance de contexte (c'est-à-dire des conditions), de sorte que le contrôleur du service web ne connaît pas le type lorsque la condition doit être désérialisée. Par exemple, un client peut poster :
{"type":"Equal","ref_val":"goofy"}
ou
{"type":"Greater","ref_val":"Pluto"}
ou plus complexe avec n'importe quel combinateur ('et', 'ou', 'pas')
{"type":"And","left":{"type":"Greater","ref_val":"Gamma"},"right":{"type":"Equal","ref_val":"Delta"}}
et donc je dois désérialiser vers un trait (dyn Condition) en utilisant les balises de type dans le balisage sérialisé...