使用 serde 反序列化变量元对象
Deserialize variable meta object with 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,那么食物的元数据将是一个字符串(国家)和一个布尔值(酒)。所以产品有一些共同的字段,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,
}
我不确定如何从这里开始,我想问一下 serde crate 是否可以做到这一点 "automatically"。
这对应于 "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(())
}
我正在寻找一种优雅的方法来反序列化以下输入:
{
"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,那么食物的元数据将是一个字符串(国家)和一个布尔值(酒)。所以产品有一些共同的字段,id、ptype 和 description 以及一些元数据。我想在 Vec<Product>
.
到目前为止,我使用了以下代码:
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,
}
我不确定如何从这里开始,我想问一下 serde crate 是否可以做到这一点 "automatically"。
这对应于 "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(())
}