我正在寻找一种优雅的方法来反序列化以下输入:
{
"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/