rust - 如何使用Serde在结构中反序列化json格式的结构数组?

标签 rust serde

假设我具有以下结构“车轮”和“汽车”,其中“汽车”可以包含汽车列表(递归定义)。

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表明您将CarsCar的概念混合在一起,在wheel中,cars是对象Car,在Car中,carsVec,具有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/

相关文章:

rust - 预期特征 core::ops::FnMut,找到类型参数

memory - 为什么原始部分不符合任何字节序?

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

rust - 如何在 Rust 中序列化 Arc<Mutex<T>>?

polymorphism - "polymorphic"返回的 Rust 特征的简单组织

rust - 如何将 [u64;N] 转换为 [u8;8*N]?

concurrency - Rust 异步等待 : check if any future in a list resolves to true concurrently?

rust - 在 Rust 中反序列化 redis 的值(FromRedisValue)

rust - 为什么没有为明确实现的类型实现特征?

json - 是否可以使用 json 的 json_serde::from_str() 获取值,其中字符串周围没有“”?