假设我有如下 JSON 数据:
{
"type": "A",
"value": [ 1, 2, 3, 4, 5 ]
}
Run Code Online (Sandbox Code Playgroud)
{
"type": "B",
"value": [ [ 1, 2, 3, 4, 5 ], [ 6, 7, 8 ] ]
}
Run Code Online (Sandbox Code Playgroud)
type确定 的类型value,在第一个示例中为Vec<u32>,在第二个示例中为Vec<Vec<u32>>。
如果我将上面的数据表示如下:
{
"type": "A",
"value": [ 1, 2, 3, 4, 5 ]
}
Run Code Online (Sandbox Code Playgroud)
如何实现 serde 反序列化以正确解码这些值?
Sve*_*ach 10
DataValue如果您为 Serde 提供足够的信息以了解如何执行此操作,则可以将 JSON 数据直接反序列化为 的实例:
#[derive(Debug, Deserialize)]\n#[serde(tag = "type", content = "value")]\nenum DataValue {\n #[serde(rename = "A")]\n TypeA(Vec<u32>),\n #[serde(rename = "B")]\n TypeB(Vec<Vec<u32>>),\n}\n\nlet data_a = r#"\n {\n "type": "A",\n "value": [1, 2, 3, 4, 5]\n }"#;\nlet a: DataValue = serde_json::from_str(data_a)?;\nRun Code Online (Sandbox Code Playgroud)\n\n\n\n如果将枚举变体命名为A和B,则可以省略#[serde(rename = "\xe2\x80\xa6")]属性。
这种序列化枚举的方式称为“相邻标记”。您可以在有关枚举序列化的 Serde 文档中了解标记枚举的各种选项。
\n\n您的Data结构包含冗余的附加标签data_type。此信息已编码在枚举中,因此我认为您不需要此信息。如果您需要此信息作为字符串,您可以向枚举添加一个方法:
impl DataValue {\n fn variant_name(&self) -> &\'static str {\n match self {\n DataValue::TypeA(_) => "A",\n DataValue::TypeB(_) => "B",\n }\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n
幸运的是,serde内置了对枚举类型的支持:
//# 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);
}
Run Code Online (Sandbox Code Playgroud)