如何将匿名枚举值序列解析为Rust元组结构体?
如何将JSON数组直接解析为包含枚举向量的元组结构体?
默认情况下,Serde对枚举的反序列化要求每个变体以带键的JSON对象形式存在(比如{"Single": 1}),但要直接解析[1, [2], [[3]]]这类纯JSON数组/数字组成的结构,你可以通过#[serde(untagged)]属性让Serde自动匹配枚举变体,无需额外的键包裹。
修改后的代码
use serde::Deserialize; #[derive(Deserialize, Debug, PartialEq, Eq)] #[serde(untagged)] // 添加该属性实现无标签枚举反序列化 enum Data { Single(i32), List(Vec<Data>), } #[derive(Deserialize, Debug, PartialEq, Eq)] struct Packet(Vec<Data>); fn main() { let packet = r#"[1, [2], [[3]]]"#; assert_eq!( serde_json::from_str::<Packet>(packet).unwrap(), Packet(vec![ Data::Single(1), Data::List(vec![Data::Single(2)]), Data::List(vec![Data::List(vec![Data::Single(3)])]) ]) ); }
原理说明
#[serde(untagged)]会让Serde放弃对枚举变体的标签校验,转而按变体定义的顺序尝试匹配输入的JSON值:
- 遇到JSON数字时,自动匹配
Single(i32)变体; - 遇到JSON数组时,自动匹配
List(Vec<Data>)变体; - 若输入值无法匹配任何变体,会返回反序列化错误。
手动实现反序列化(可选,用于精细控制)
如果需要更灵活的逻辑,也可以手动实现Deserialize trait:
use serde::{de, Deserialize, Deserializer}; use std::fmt; #[derive(Debug, PartialEq, Eq)] enum Data { Single(i32), List(Vec<Data>), } impl<'de> Deserialize<'de> for Data { fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de>, { struct DataVisitor; impl<'de> de::Visitor<'de> for DataVisitor { type Value = Data; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("a number or an array of Data") } fn visit_i32<E>(self, value: i32) -> Result<Data, E> where E: de::Error, { Ok(Data::Single(value)) } fn visit_seq<A>(self, mut seq: A) -> Result<Data, A::Error> where A: de::SeqAccess<'de>, { let mut vec = Vec::new(); while let Some(element) = seq.next_element()? { vec.push(element); } Ok(Data::List(vec)) } } deserializer.deserialize_any(DataVisitor) } } #[derive(Deserialize, Debug, PartialEq, Eq)] struct Packet(Vec<Data>); fn main() { let packet = r#"[1, [2], [[3]]]"#; assert_eq!( serde_json::from_str::<Packet>(packet).unwrap(), Packet(vec![ Data::Single(1), Data::List(vec![Data::Single(2)]), Data::List(vec![Data::List(vec![Data::Single(3)])]) ]) ); }
这种方式通过自定义Visitor,明确处理JSON数字和数组两种输入格式,将其分别映射到对应的枚举变体。
内容的提问来源于stack exchange,提问作者Paweł Rubin
相关产品推荐
相关产品推荐

