如何在Rust中使用serde解析这个JSON文件?

baubqpgj  于 2023-02-26  发布在  其他
关注(0)|答案(1)|浏览(353)

我是Rust的新手。我正在尝试解析一个JSON文件,并将数据存储为Rust中的对象。
下面是JSON文件的外观:

{
"comment": ["some comments"],
"data": [
    ["name", "line 1"],
    ["name", ["line 1", "line 2"]],
    ......
    ["name", "line 1"]
]
//(The line where the error is coming)

}

我做了这样的结构:

#[derive(Debug, Deserialize)]
struct my_data {
    comment: String,
    data: Vec<sub_data>,
}
#[derive(Debug, Deserialize)]
struct sub_data {
    name: String, 
    pattern: Vec<String>,
}

然后我尝试了这个代码,但得到了一个错误:

Error("missing field `Comment`", line: 1381, column: 1)',

代码:

pub fn read_json () {
    let path = "./src/my_file.json";
    let data = fs::read_to_string(path).expect("Unable to read file");
    let obj: my_data = serde_json::from_str(&data).expect("Unable to parse");
    println!("{:?}", obj);
    return
}

有人能帮我修修吗?

qvtsj1bj

qvtsj1bj1#

首先,JSON不是PascalCase格式的,这个属性告诉serde查找“Comment”和“Data”,而不是原来的名称。(默认情况下)跳过所有其他键,并让您知道它没有找到任何名为“Comment”的键。JSON可能是camelCase,但由于所有键都是单个单词,我将不使用rename属性,您可以查看container attributes documentation,自己决定。
其次,在rust类型中没有正确表示JSON数组,用SubData表示的数组很好,因为serde会假设它们是结构体成员,但是用SubData.pattern表示的数组不是数组就是单个字符串。所以你不能把它直接反序列化为一个类型,这就是无标记枚举StringOrList要处理的,如果你想让它一直是Vec您可以使用deserialize_with属性或serde_with crate

#[derive(Debug, Deserialize)]
struct MyData {
    comment: Vec<String>,
    data: Vec<SubData>,
}

#[derive(Debug, Deserialize)]
struct SubData {
    name: String, 
    pattern: StringOrList,
}

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

相关问题