2017-10-05 8 views
3

J'ai un arbre de structs serde annoté et il réussit à l'analyse du XML exemple, y compris ce fragment:Failed pour analyser XML avec un élément en option avec serde-xml-rs

<bmsg> 
    <cmsg> 
     <!-- ... --> 
    <cmsg> 
<bmsg> 

Maintenant, je suis essai avec un grand exemple de fichier XML et les structures suivantes échouent car il manque parfois <cmsg>..</cmsg>. Je désérialisation cela en utilisant:

#[derive(Serialize,Deserialize, Debug)] 
struct A { 
    #[serde(rename="bmsg")] 
    messages: B,     // <==== 
} 

#[derive(Serialize,Deserialize, Debug)] 
struct B { // bmsg 
    #[serde(rename="cmsg")] 
    list: Vec<C>, 
} 

ce qui a entraîné une erreur dans la deuxième struct:

panicked at 'called `Result::unwrap()` on an `Err` value: missing field `cmsg` 

J'ai changé le premier struct d'avoir un Vec<> il peut traiter un élément facultatif:

#[derive(Serialize,Deserialize, Debug)] 
struct A { 
    #[serde(rename="bmsg")] 
    messages: Vec<B>,   // <==== 
} 

#[derive(Serialize,Deserialize, Debug)] 
struct B { // bmsg 
    #[serde(rename="cmsg")] 
    list: Vec<C>, 
} 

Mais serde continue à donner la même erreur. J'ai aussi essayé Option<>, mais je n'ai rien trouvé. Ce qui me déroute le plus, c'est que j'utilise Vec<> partout et je n'ai jamais rencontré ce problème.

Répondre

4

Il semblerait Option<T> signifie que l'article existe, il est simplement vide de contenu.

The documentation seems to suggest using l'attribut default, de dire la désérialiseur d'utiliser la mise en œuvre du Default trait pour le type si elle ne se trouve.

Avec cela à l'esprit, peut-être cela fonctionnerait pour vous:

#[derive(Serialize,Deserialize, Debug)] 
struct A { 
    #[serde(rename = "bmsg")] 
    messages: B, 
} 

#[derive(Serialize,Deserialize, Debug)] 
struct B { // bmsg 
    #[serde(rename = "cmsg", default)] // <----- use default to call `Default::default()` against this vector 
    list: Vec<C>, 
} 

Vous pouvez trouver the code I used to check this in the Playground. Il ne fonctionnera pas dans le Playground, mais il produit vos résultats attendus en cours d'exécution localement.

+2

Ceci est une réponse correcte et très bien élaborée. Note J'ai essayé # [serde (par défaut)], mais seulement sur la première structure:/Merci! – user103185