假设我具有以下结构“车轮”和“汽车”,其中“汽车”可以包含汽车列表(递归定义)。
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Wheel {
#[serde(default, rename(deserialize = "Car"))]
pub car: Car,
#[serde(default, rename(deserialize = "Wheel Diameter"))]
pub wheel_diameter: f64,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Car {
#[serde(default, rename(deserialize = "Dealer Price"))]
pub dealer_price: f64,
#[serde(default, rename(deserialize = "Cars"))]
pub cars: Vec<Car>,
}
impl Default for Wheel {
fn default() -> Wheel {
Wheel {
car: Car {
..Default::default()
},
wheel_diameter: 5.0,
}
}
}
impl Default for Car {
fn default() -> Car {
Car {
dealer_price: 1.0,
cars: Vec::new(),
}
}
}
fn main() {
let str_input = r#"[
{
"Wheel Diameter": 5.2,
"Car": {
"Dealer Price": 500,
"Cars": [
{
"Car": {
"Dealer Price": 1500
}
}
]
}
}
]"#;
let cars: Vec<Wheel> = serde_json::from_str(str_input).unwrap();
println!("cars {:#?}", cars);
}
1)当我使用
str_input
(基本上是一个转义的免费JSON格式的字符串)运行以上代码时,得到以下输出:cars [
Wheel {
car: Car {
dealer_price: 500.0,
cars: [
Car {
dealer_price: 0.0,
cars: [],
},
],
},
wheel_diameter: 5.2,
},
]
顶层可以正确初始化默认值,但是“嵌套汽车”在Vec中无法正确初始化。如何使它在Serde中工作?我尝试在各个地方添加
with = "serde_with::json::nested"
,但这似乎没有用。我提示Error("invalid type: sequence, expected valid json object", line: 1, column: 61
会出错这是否意味着我必须以某种方式编写自定义反序列化?
2)什么是确保递归反序列化不会“消耗”内存的好方法? Rust的新手。在Golang中,您可以通过在负责容纳反序列化json的结构上添加一些带有字符串标记的属性来“神奇地”反序列化这种类型的结构。
注意:从域建模的角度来看,我意识到在Car结构中使用“cars”向量可能并不“有意义”,但是我必须进行一些字段重命名以确保我不会在野外共享代码应该共享。因此,即使名称在概念上可能没有意义,代码的结构也反射(reflect)了需要解决的问题。
最佳答案
您的表示没有多大意义,您提供的json表明您将Cars
和Car
的概念混合在一起,在wheel中,cars
是对象Car
,在Car
中,cars
是Vec
,具有Car
。那没有道理。 json看起来不对。无论如何,要在Rust中解决此问题,您需要表达差异,例如:
您可以使用Wheel
,因为它已经有一个car
字段:
#[serde(default, rename = "Cars")]
pub cars: Vec<Wheel>,
使用中间结构:
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Foo {
#[serde(default, rename = "Car")]
car: Car,
}
因此将
Car.cars
更改为:#[serde(default, rename = "Cars")]
pub cars: Vec<Foo>,
或者您可以使用一个枚举,因为它看起来像您的
Cars
是一个枚举,您只向我们展示一种类型:#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum Foo {
Car(Car),
}
您还可以通过以下方法解决问题:
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Wheel {
#[serde(flatten, default)]
pub car: Foo, // or pub foo: Foo, if it make more sense
#[serde(default, rename = "Wheel Diameter")]
pub wheel_diameter: f64,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Car {
#[serde(default, rename = "Dealer Price")]
pub dealer_price: f64,
#[serde(default, rename = "Cars")]
pub cars: Vec<Foo>, // or foos if it make more sense
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum Foo {
Car(Car),
}
您还可以进行自定义反序列化。
考虑到您的内存问题,如果您尝试创建递归类型,Rust将阻止您,
Vec
已经为您提供了防止这种情况的间接方法。
关于rust - 如何使用Serde在结构中反序列化json格式的结构数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61995477/