rust - 使用Serde反序列化变量元对象

标签 rust serde

我正在寻找一种优雅的方法来反序列化以下输入:

{
  "products": [

    {
      "id": 1,
      "ptype": "Clothes",
      "description": "some data about clothes",
      "metadata": {
        "colors" : ["blue", "green"],
        "web": false,
        "size": 2
      }
    },
    {
      "id": 4,
      "ptype": "Food",
      "description": "text for foods",
      "metadata": {
        "country": "France",
        "wine": true
      }
    },
    {
      "id": 12,
      "ptype": "EmptyPlaceholder",
      "description": "nothing at all",
      "metadata": {
      }
    }
  ]
}

json包含一系列产品。可以通过ptype字段标识产品。根据字段的类型,元数据对象会有所不同。例如,如果ptype是Food,则food的元数据将是一个字符串(国家)和一个 bool 值(葡萄酒)。因此,产品具有一些共同的字段,包括id,ptype和description以及一些元数据。我想在Vec<Product>中反序列化此JSON文件。

到目前为止,我已经使用以下代码:
use serde::{Deserialize};
use serde_json::Result;

#[derive(Deserialize, Debug)]
struct ClothesData {
    colors : Vec<String>,
    web : bool,
    size: u32,
}

#[derive(Deserialize, Debug)]
struct FoodData {
    country: String,
    wine: bool,
}

#[derive(Deserialize, Debug)]
struct EmptyData {

}

#[derive(Deserialize, Debug)]
enum Metadata {
    ClothesData,
    FoodData,
    EmptyData,
}

#[derive(Deserialize, Debug)]
enum  Ptype {
    Clothes,
    Food,
    EmptyPlaceholder
}

#[derive(Deserialize, Debug)]
struct Product {
    id: u32,
    ptype: Ptype,
    description: Option<String>,
    metadata: Metadata,

}

我不知道如何从这里开始,我想问问锯木箱是否可以“自动”进行。

最佳答案

这对应于"adjacently tagged" serde枚举表示形式:

use serde::Deserialize;
use serde_json::Result;

#[derive(Deserialize, Debug)]
struct Clothes {
    colors: Vec<String>,
    web: bool,
    size: u32,
}

#[derive(Deserialize, Debug)]
struct Food {
    country: String,
    wine: bool,
}

#[derive(Deserialize, Debug)]
struct Empty {}

#[derive(Deserialize, Debug)]
#[serde(tag = "ptype", content = "metadata")]
enum Kind {
    Clothes(Clothes),
    Food(Food),
    EmptyPlaceholder(Empty),
}

#[derive(Deserialize, Debug)]
struct Product {
    id: u32,
    description: Option<String>,
    #[serde(flatten)]
    kind: Kind,
}

#[derive(Deserialize, Debug)]
struct Root {
    products: Vec<Product>,
}

fn main() -> Result<()> {
    let data = r#"
    {
        "products": [

            {
              "id": 1,
              "ptype": "Clothes",
              "description": "some data about clothes",
              "metadata": {
                "colors" : ["blue", "green"],
                "web": false,
                "size": 2
              }
            },
            {
              "id": 4,
              "ptype": "Food",
              "description": "text for foods",
              "metadata": {
                "country": "France",
                "wine": true
              }
            },
            {
              "id": 12,
              "ptype": "EmptyPlaceholder",
              "description": "nothing at all",
              "metadata": {
              }
            }
        ]
    }"#;

    let root: Root = serde_json::from_str(data)?;
    println!("{:#?}", root);

    Ok(())
}

关于rust - 使用Serde反序列化变量元对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61645924/

相关文章:

oop - 在 OOP Rust 中,值在构造函数和 setter 中的生命周期不够长

rust - 将默认字符串值添加到反序列化的 serde 结构失败,特征 Deserialize<'_> 未实现

rust - 使用 Serde 反序列化时如何忽略额外的元组项? ("trailing characters"错误)

rust - Rust Serde反序列化混合数组

rust - 序列化结构上的子属性似乎不起作用

mongodb - 使用 Rust Mongo 驱动程序原型(prototype)时,如何将 chrono::DateTime 字段序列化为 ISODate?

rust - 如何在 Rust 中编译多文件 crate?

rust - 如何在 Rust 中使用串口?

rust - UDP服务器示例如何安全?

rust - 为什么生成的 future 不由 tokio_core::reactor::Core 执行?