在Rust中,如何在多个结构中反序列化JSON?

lf5gs5x2  于 2023-05-29  发布在  其他
关注(0)|答案(3)|浏览(185)

假设我们有以下JSON:

{
   name:"John",
   age:"30"
}

和以下两个结构:

struct Name {
   name: String;
}

struct Age {
   age: i32
}

什么是将JSON反序列化为结构体的有效方法?

hkmswyz6

hkmswyz61#

创建第三个结构体,包含其他每个结构体,并使用#[serde(flatten)]将每个字段反序列化,就像它是一个单一的平面结构体一样:

use serde::Deserialize;

#[derive(Debug, Deserialize)]
struct Name {
    name: String,
}
#[derive(Debug, Deserialize)]
struct Age {
    age: i32,
}
#[derive(Debug, Deserialize)]
struct Person {
    #[serde(flatten)]
    name: Name,
    #[serde(flatten)]
    age: Age,
}

fn main() {
    dbg!(serde_json::from_str::<Person>(r#"{ "name": "John", "age": 30 }"#).unwrap());
    // Person {
    //     name: Name {
    //         name: "John",
    //     },
    //     age: Age {
    //         age: 30,
    //     },
    // }
}

playground

sqxo8psd

sqxo8psd2#

这看起来是一种非常不寻常的反序列化JSON的方法。好奇是什么让你想要这样的结构。
最简单的方法应该是以下方法之一:

  • 只需将JSON字符串解析为Value示例并从那里获取它;
  • 正如PitaJ所建议的,使用第三个结构体#[serde(flatten)]

如果你想有更多的这样的结构,每个结构都有一个同名的属性,你可以编写一个宏或自定义反序列化器。
作为一个侧节点,可以使用小写结构名,但在Rust中并不习惯。

1szpjjfi

1szpjjfi3#

正如@at54321所建议的,这里有一种使用Value的方法:

use std::fmt;
use std::fs::File;
use serde::Deserialize;

#[derive(Deserialize)]
struct Name {
    name: String
}

#[derive(Deserialize)]
struct Age {
    age: u32
}

fn main() {

    let file = File::open("person.json").unwrap();
    let value: serde_json::Value = serde_json::from_reader(file).unwrap();
    let name= Name {
        name: serde_json::from_value(value["name"].clone()).unwrap()
    };
    let age = Age {
        age: serde_json::from_value(value["age"].clone()).unwrap()
    };
}

相关问题