使用 Serde 反序列化具有多种类型字段的 JSON

2024-01-12

我有一些 JSON 文本数据,其字段可以是字符串或字符串数​​组。以下是四个可能的示例:

{
        "keya": "some string",
        "keyb": "some string"
}


{
        "keya": "some string",
        "keyb": ["some string", "some string"]
}

{
        "keya": ["some string", "some string"],
        "keyb": "some string"
}

{
        "keya": ["some string", "some string"],
        "keyb": ["some string", "some string"]
}

如何创建一个类型,允许我使用 Serde 反序列化此类 JSON 文本数据?


这个答案早于OP作为评论给出的额外要求,但由于额外的要求使其成为一个单独的问题,因此保持原样。


处理尾随逗号

由于每个右括号之前都存在尾随逗号,问题中提供的输入数据不是有效的 JSON}。如果你must使用尾随逗号,然后使用常规serde_jsoncrate 不适合您的需求,您可能想要替换所有用法serde_json带有支持尾随逗号的板条箱,例如the json5 crate https://crates.io/crates/json5. The json5提供了一个类似于serde_json,所以下面的答案仍然有效。

处理可以是多种类型的字段

处理具有多种可能值类型的 JSON 字段可以使用enum持有一个String or a Vec<String>,与#[serde(untagged)]属性。看枚举表示 https://serde.rs/enum-representations.html有关该属性的详细信息,请参阅 serde 的官方文档。

完整示例:

use serde::{Serialize, Deserialize};

#[derive(Debug, Serialize, Deserialize)]
#[serde(untagged)]
enum StringOrStringVec {
    String(String),
    Vec(Vec<String>)
}

#[derive(Debug, Serialize, Deserialize)]
struct MyObj {
    keya: StringOrStringVec,
    keyb: StringOrStringVec,
}

fn main() {
    let input_json = r#"
        {
            "keya": "some string",
            "keyb": ["some string", "some string"]
        }
    "#;
    let my_obj: MyObj = serde_json::from_str(input_json).unwrap();
    println!("{:?}", my_obj);
    
    let input_json = r#"
        {
            "keya": ["some string", "some string"],
            "keyb": "some string"
        }
    "#;
    let my_obj: MyObj = serde_json::from_str(input_json).unwrap();
    println!("{:?}", my_obj);
}

输出示例:

MyObj { keya: String("some string"), keyb: Vec(["some string", "some string"]) }
MyObj { keya: Vec(["some string", "some string"]), keyb: String("some string") }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 Serde 反序列化具有多种类型字段的 JSON 的相关文章

随机推荐