如何让Serde正确将JSON反序列化为指定Rust枚举类型?
解决Serde反序列化Rust枚举时的变体匹配问题
你遇到的问题是Serde默认将所有字符串类型的JSON值都解析为带字符串参数的Pass变体,而没有匹配到Fail和Absent单元变体。这个需求完全可以实现,下面提供两种可行方案:
方案一:使用Serde内置属性快速解决
通过给枚举添加Serde属性,指定变体名称与JSON字符串的映射关系,并将未匹配的字符串统一解析为Pass变体:
use serde::Deserialize; use serde_json::Error; #[derive(Debug, Deserialize)] #[serde(rename_all = "snake_case")] // 确保变体名称与JSON小写字符串匹配 enum TestResult { Fail, Absent, #[serde(other)] // 所有不匹配前面变体的字符串都解析为Pass Pass(String), } fn main() -> Result<(), Error> { // 测试"fail"解析为Fail变体 let json_fail = "\"fail\""; let result_fail: TestResult = serde_json::from_str(json_fail)?; println!("{:?}", result_fail); // 输出: Fail // 测试"absent"解析为Absent变体 let json_absent = "\"absent\""; let result_absent: TestResult = serde_json::from_str(json_absent)?; println!("{:?}", result_absent); // 输出: Absent // 测试普通字符串解析为Pass变体 let json_pass = "\"test_passed\""; let result_pass: TestResult = serde_json::from_str(json_pass)?; println!("{:?}", result_pass); // 输出: Pass("test_passed") Ok(()) }
关键说明
#[serde(rename_all = "snake_case")]:自动将枚举变体名称转换为小写蛇形命名,确保Fail对应JSON中的"fail",Absent对应"absent"。#[serde(other)]:标记Pass变体为"兜底"选项,任何不匹配前面单元变体的字符串都会被解析为该变体的参数。
方案二:自定义反序列化逻辑(更灵活)
如果需要更精细的匹配规则(比如区分大小写、处理特殊字符串),可以实现自定义的反序列化逻辑:
use serde::de::{self, Visitor}; use serde::{Deserialize, Deserializer}; use std::fmt; #[derive(Debug)] enum TestResult { Fail, Absent, Pass(String), } impl<'de> Deserialize<'de> for TestResult { fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de>, { // 定义自定义Visitor处理字符串解析 struct TestResultVisitor; impl<'de> Visitor<'de> for TestResultVisitor { type Value = TestResult; // 提示预期的输入格式 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("a string representing test result") } // 处理字符串类型的JSON值 fn visit_str<E>(self, value: &str) -> Result<TestResult, E> where E: de::Error, { match value { "fail" => Ok(TestResult::Fail), "absent" => Ok(TestResult::Absent), // 其他所有字符串都转为Pass变体 s => Ok(TestResult::Pass(s.to_string())), } } } // 告诉Deserializer使用自定义Visitor解析字符串 deserializer.deserialize_str(TestResultVisitor) } } // 测试逻辑与方案一一致
这种方式完全由你控制匹配规则,适合复杂场景的需求。
内容的提问来源于stack exchange,提问作者Subhrajyoti Das
相关产品推荐
相关产品推荐

