如何使用Serde从带连字符的字符串反序列化枚举变体?
Serde反序列化含连字符的枚举字段解决方案
你可以通过Serde的属性注解,将枚举变体与JSON中带连字符的字符串值做映射,不需要修改枚举变体的合法命名,下面分两种场景给出实现方式:
单个变体单独映射
如果只有部分枚举变体需要对应带连字符的JSON值,直接给目标变体添加#[serde(rename = "目标JSON字符串")]注解即可:
首先确保Cargo.toml中添加依赖:
[dependencies] serde = { version = "1.0", features = ["derive"] } serde_json = "1.0"
然后编写Rust代码:
use serde::Deserialize; #[derive(Debug, Deserialize)] enum Fubar { // 将变体FooBar映射到JSON中的"foo-bar" #[serde(rename = "foo-bar")] FooBar, // 其他正常命名的变体 BazQux, } #[derive(Debug, Deserialize)] struct Data { fubar: Fubar, } fn main() { let json_str = r#"{"fubar": "foo-bar"}"#; let data: Data = serde_json::from_str(json_str).unwrap(); println!("{:?}", data); // 输出: Data { fubar: FooBar } }
批量变体统一映射
如果所有枚举变体对应的JSON值都是烤肉串格式(即单词用连字符分隔,比如foo-bar、baz-qux),可以给整个枚举添加#[serde(rename_all = "kebab-case")]注解,Serde会自动将枚举变体的命名(驼峰/蛇形)转换为烤肉串格式:
use serde::Deserialize; #[derive(Debug, Deserialize)] // 自动将变体名转为烤肉串格式 #[serde(rename_all = "kebab-case")] enum Fubar { FooBar, // 对应JSON中的"foo-bar" BazQux, // 对应JSON中的"baz-qux" } #[derive(Debug, Deserialize)] struct Data { fubar: Fubar, } fn main() { let json_str = r#"{"fubar": "baz-qux"}"#; let data: Data = serde_json::from_str(json_str).unwrap(); println!("{:?}", data); // 输出: Data { fubar: BazQux } }
这两种方式都能完美解决JSON字段含连字符但枚举变体命名受限的问题,不需要额外的自定义反序列化逻辑。
内容的提问来源于stack exchange,提问作者In Hoc Signo
相关产品推荐
相关产品推荐

