如何为同一Serde字段接受多个反序列化名称?

14

我想使用Serde来反序列化基于以下结构体的JSON (serde-json) 和 XML (serde-xml-rs) 文件:

use serde_derive::Deserialize;

#[derive(Debug, Clone, PartialEq, Deserialize)]
pub struct SchemaConfig {
    pub name: String,
    #[serde(rename = "Cube")]
    pub cubes: Vec<CubeConfig>,
}
我正在反序列化的字段根据文件类型具有不同的名称。在这种情况下,我希望一个 JSON 文件有一个名为cubes的键,并带有立方体列表,但在 XML 中等效的是多个 <Cube /> 元素。
我无法想出如何接受cubesCube作为反序列化的键。我找到的最接近的是 #[serde(rename = "Cube")] 选项,但当我使用它时,JSON 反序列化将停止工作,因为它仅接受Cube键。如果我删除该选项,则 XML 反序列化将停止工作,因为它仅接受cubes作为键。
在 Serde 中是否有一种简单的方法来实现这一点?
1个回答

18
我鼓励您阅读Serde文档。字段属性章节介绍了alias属性,重点在于:

#[serde(alias = "name")]

从给定名称或其Rust名称反序列化该字段。可以重复使用以指定同一字段的多个可能名称

use serde::Deserialize; // 1.0.88
use serde_json; // 1.0.38

#[derive(Debug, Deserialize)]
struct SchemaConfig {
    #[serde(alias = "fancy_square", alias = "KUBE")]
    cube: [i32; 3],
}

fn main() -> Result<(), Box<std::error::Error>> {
    let input1 = r#"{
        "fancy_square": [1, 2, 3]
    }"#;

    let input2 = r#"{
        "KUBE": [4, 5, 6]
    }"#;

    let one: SchemaConfig = serde_json::from_str(input1)?;
    let two: SchemaConfig = serde_json::from_str(input2)?;

    println!("{:?}", one);
    println!("{:?}", two);

    Ok(())
}

我希望JSON文件具有一个键和立方体列表,但在XML中等效的是多个元素。
这肯定听起来像你想要两个不同的文件结构。在这种情况下,请查看类似于以下内容:
- 如何使用Serde在反序列化期间转换字段? - 如何在不包括枚举变量名称的情况下序列化枚举?

2
感谢您提供的代码示例。我确实阅读了文档,但是从文档中并不清楚如何指定多个“alias”值。您在这里提供的代码示例让我完全明白了。 - Gary Sheppard
这似乎是唯一的解决方法,但它有漏洞。考虑fancy_squreKUBE可以在同一个文件或不同的文件中。 - ibigbug

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