【问题标题】:Serde deserialising unpredictable json structureSerde反序列化不可预测的json结构
【发布时间】:2022-11-29 23:03:19
【问题描述】:

我将收到具有以下格式的 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 的类型?

【问题讨论】:

    标签: rust serde


    【解决方案1】:

    处理尾随逗号

    由于尾随逗号的存在,问题中提供的输入数据不是有效的 JSON。如果您必须使用尾随逗号,那么传统的 serde_json crate 不适合您的需求,您可能希望将 serde_json 的所有用法替换为支持尾随逗号的 crate,如 the json5 cratejson5 提供了一个类似于serde_json 的API,所以下面的答案仍然有效。

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

    处理具有多种可能值类型的 JSON 字段可以使用 enum 完成,该 enum 包含 StringVec<String> 以及 #[serde(untagged)] 属性。参见 serde 官方文档中的Enum representations

    完整示例:

    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") }
    

    See it in action on Rust Playground

    【讨论】:

      【解决方案2】:

      JSON 是一种普遍存在的开放标准格式,它使用人类可读的文本来传输由键值对组成的数据对象。

      { "name": "约翰·杜伊", “年龄”:43岁, “地址”: { “街道”:“唐宁街 10 号”, “城市”:“伦敦” }, “电话”:[ "+44 1234567", “+44 2345678” ] } 您可能会发现自己需要通过三种常见方式在 Rust 中处理 JSON 数据。

      作为文本数据。您在 HTTP 端点上接收、从文件中读取或准备发送到远程服务器的未处理的 JSON 数据字符串。 作为无类型或松散类型的表示。也许您想在传递某些 JSON 数据之前检查它是否有效,但不知道它包含的内容的结构。或者您想进行非常基本的操作,例如在特定位置插入钥匙。 作为强类型 Rust 数据结构。当您希望所有或大部分数据符合特定结构并希望在不受 JSON 松散性质的影响的情况下完成实际工作时。

      【讨论】:

        猜你喜欢
        • 2016-04-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-12-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多