使用serde-xml-rs解析可选元素的XML失败

6

我有一个serde注释的结构体树,成功解析了样本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<>,从未遇到过这个问题。
1个回答

8

看起来 Option<T> 意味着该项 存在,只是没有内容。

文档似乎建议使用 default 属性,告诉反序列化器在找不到类型的 Default 特质 实现时使用它。

考虑到这一点,也许这对你有用:

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

你可以在Playground中查看我用来检查这个的代码。它不能在Playground中运行,但在本地运行时会产生期望的结果。

2
这是一个正确且非常详细的答案。注意,我尝试过使用#[serde(default)],但只在第一个结构体上:/ 谢谢! - user103185

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接