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

Hap*_*ine 6 rust serde

我有一些 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"]
}
Run Code Online (Sandbox Code Playgroud)

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

kot*_*aki 7

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


处理尾随逗号

由于每个右括号之前都存在尾随逗号,问题中提供的输入数据不是有效的 JSON }。如果您必须使用尾随逗号,那么传统的serde_jsoncrate 不适合您的需求,您可能需要将所有用法替换serde_json为支持尾随逗号的 crate,例如crate json5提供json5了一个类似于serde_json,因此以下答案仍然有效。

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

enum处理具有多种可能值类型的 JSON 字段可以使用包含 aString或 a 的Vec<String>和属性来完成#[serde(untagged)]。请参阅枚举表示有关该属性的详细

完整示例:

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);
}
Run Code Online (Sandbox Code Playgroud)

输出示例:

MyObj { keya: String("some string"), keyb: Vec(["some string", "some string"]) }
MyObj { keya: Vec(["some string", "some string"]), keyb: String("some string") }
Run Code Online (Sandbox Code Playgroud)

在 Rust Playground 上查看它的实际应用


归档时间:

查看次数:

3555 次

最近记录:

2 年 前