2017-10-05 128 views
3

我有SERDE标注结构的树,它在解析XML示例,其中包括该片段成功:失败与SERDE-XML-RS的可选元素解析XML

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

现在我测试与一个大的示例XML文件和以下结构失败,因为有时<cmsg>..</cmsg>丢失。我反序列化这样使用:

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

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

其中在第二结构导致错误:

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

我改变了第一个结构有Vec<>所以它可以处理一个可选元素:

#[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>, 
} 

但serde继续给出同样的错误。我也尝试Option<>,但没有得到任何地方。

最让我感到困惑的是我在各地使用Vec<>,从未遇到过这个问题。

回答

4

这样看来Option<T>意味着该项目确实存在,它仅仅是空洞的内容。

The documentation seems to suggest usingdefault属性,告诉解串器使用Default trait的实施类型如果无法找到

考虑到这一点,也许这会为你工作:

#[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>, 
} 

你可以找到the code I used to check this in the Playground。它不会在Playground中运行,但会产生您在本地运行的预期结果。

+2

这是一个正确和很好阐述的答案。注意我试过#[serde(默认)],但只在第一个结构上:/谢谢! – user103185