如何反序列化包含嵌套JSON字符串的JSON对象?
解决嵌套JSON字符串的反序列化问题
这个问题我之前也碰到过!核心原因是你JSON里的b字段是字符串形式的JSON,但你的Test结构体里b定义的是B类型,serde默认会直接把它当成结构体来解析,自然就类型不匹配 panic 了。给你两种实用的解决办法:
方法一:自定义反序列化函数(推荐)
利用serde的deserialize_with属性,给b字段指定一个自定义的反序列化逻辑——先把字符串解析出来,再把这个字符串转成B结构体。
首先写一个通用的辅助函数,它能把JSON字符串反序列化成任意实现了Deserialize的类型:
use serde::{Deserialize, Deserializer}; fn deserialize_json_string<'de, T, D>(deserializer: D) -> Result<T, D::Error> where T: Deserialize<'de>, D: Deserializer<'de>, { // 先把输入反序列成字符串 let json_str = String::deserialize(deserializer)?; // 再把字符串解析成目标类型,转换错误格式适配serde的错误类型 serde_json::from_str(&json_str).map_err(serde::de::Error::custom) }
然后修改你的Test结构体,给b字段加上属性:
#[derive(Deserialize)] struct B { c: String, d: u32, } #[derive(Deserialize)] struct Test { a: String, // 指定用我们写的函数来反序列化b字段 #[serde(deserialize_with = "deserialize_json_string")] b: B, } // 现在再运行你的反序列化代码就不会panic了 fn main() { let object: Test = serde_json::from_str( r#" { "a": "string", "b": "{\"c\":\"c_string\",\"d\":1234}" } "#, ).unwrap(); println!("a: {}, c: {}, d: {}", object.a, object.b.c, object.b.d); }
方法二:中间结构体中转
如果不想写自定义函数,也可以先把JSON反序列化到一个中间结构体,手动把b字段的字符串解析成B,再转换成最终的Test结构体:
use serde::Deserialize; #[derive(Deserialize)] struct B { c: String, d: u32, } #[derive(Deserialize)] // 中间结构体,b字段是String类型 struct IntermediateTest { a: String, b: String, } #[derive(Deserialize)] struct Test { a: String, b: B, } fn main() { let intermediate: IntermediateTest = serde_json::from_str( r#" { "a": "string", "b": "{\"c\":\"c_string\",\"d\":1234}" } "#, ).unwrap(); // 手动把字符串解析成B let b = serde_json::from_str(&intermediate.b).unwrap(); let object = Test { a: intermediate.a, b, }; println!("a: {}, c: {}, d: {}", object.a, object.b.c, object.b.d); }
注意:示例里用了
unwrap()是为了简化代码,实际生产环境中建议用Result来处理错误,避免程序panic。
内容的提问来源于stack exchange,提问作者Nils André
相关产品推荐
相关产品推荐

