比方说我有如下的JSON数据:
{
"type": "A",
"value": [ 1, 2, 3, 4, 5 ]
}
{
"type": "B",
"value": [ [ 1, 2, 3, 4, 5 ], [ 6, 7, 8 ] ]
}
type
确定value
的类型,第一个示例为Vec<u32>
,第二个示例为Vec<Vec<u32>>
。
如果我将上述数据表示如下:
enum DataValue {
TypeA(Vec<u32>),
TypeB(Vec<Vec<u32>>)
}
struct Data {
data_type: String,
value: DataValue
}
如何实现Serde反序列化以正确解码这些值?
答案 0 :(得分:1)
幸运的是,serde
对enum type具有内置支持:
//# serde = { version = "1.0.99", features = ["derive"] }
//# serde_json = "1.0.40"
use serde::Deserialize;
#[derive(Deserialize, Debug)]
#[serde(tag = "type")]
enum Data {
A { value: Vec<u32> },
B { value: Vec<Vec<u32>> },
}
fn main() {
let a: Data = serde_json::from_str(r#"{"type": "A", "value": [ 1, 2, 3, 4, 5 ]}"#).unwrap();
let b: Data =
serde_json::from_str(r#"{"type": "B", "value": [[1, 2, 3, 4, 5], [6, 7, 8 ]]}"#).unwrap();
println!("{:?}", a);
println!("{:?}", b);
}
答案 1 :(得分:1)
如果您向Serde提供足够的信息来知道如何执行此操作,则可以直接将JSON数据反序列化为DataValue
的实例:
#[derive(Debug, Deserialize)]
#[serde(tag = "type", content = "value")]
enum DataValue {
#[serde(rename = "A")]
TypeA(Vec<u32>),
#[serde(rename = "B")]
TypeB(Vec<Vec<u32>>),
}
let data_a = r#"
{
"type": "A",
"value": [1, 2, 3, 4, 5]
}"#;
let a: DataValue = serde_json::from_str(data_a)?;
如果将枚举变量命名为A
和B
,则可以省略#[serde(rename = "…")]
属性。
这种枚举序列的方式称为“相邻标记”。您可以在Serde documentation on enum serialization中了解标记枚举的各种选项。
您的Data
结构包含冗余的附加标签data_type
。该信息已经在枚举中进行了编码,因此我认为您不需要此信息。如果您需要将此信息作为字符串,则可以向枚举添加方法:
impl DataValue {
fn variant_name(&self) -> &'static str {
match self {
DataValue::TypeA(_) => "A",
DataValue::TypeB(_) => "B",
}
}
}
答案 2 :(得分:-3)
这可能是一个人的看法,但我通常会尽量避免对枚举进行序列化/反序列化。
在C ++中会不会接近同一件事?
struct DataValue final{
TypeA(Vec<u32>) final,
TypeB(Vec<Vec<u32>>) final
}