在Rust中如何将JSON反序列化为多个结构体?
高效将指定JSON反序列化为两个Rust结构体的方法
先修正问题中的语法问题
原JSON的键未加双引号(不符合JSON规范),原Rust结构体字段用分号分隔(不符合Rust语法),修正后内容如下:
给定JSON数据:
{ "name": "John", "age": "30" }
修正后的Rust结构体:
struct Name { name: String, } struct Age { age: i32, }
解决方案(基于Rust标准JSON处理库serde+serde_json)
方法一:临时结构体一次性解析(推荐,性能最优)
只解析一次JSON,再将字段拆分到两个目标结构体,避免重复解析开销。
- 给临时结构体和目标结构体派生
Deserialize宏,用于反序列化 - 先把JSON解析到临时结构体,再提取字段构造目标实例
代码示例:
use serde::Deserialize; // 临时结构体,匹配JSON的完整结构 #[derive(Deserialize)] struct TempUser { name: String, // 处理JSON中字符串类型的数字转i32,这里用serde_aux简化转换 #[serde(deserialize_with = "serde_aux::prelude::deserialize_number_from_string")] age: i32, } #[derive(Deserialize, Debug)] struct Name { name: String, } #[derive(Deserialize, Debug)] struct Age { age: i32, } fn main() -> Result<(), Box<dyn std::error::Error>> { let json_str = r#"{ "name": "John", "age": "30" }"#; // 一次性解析JSON到临时结构体 let temp_user: TempUser = serde_json::from_str(json_str)?; // 构造目标结构体 let name_struct = Name { name: temp_user.name }; let age_struct = Age { age: temp_user.age }; println!("{:?}", name_struct); println!("{:?}", age_struct); Ok(()) }
如果不想依赖serde_aux,可以手动处理类型转换:把临时结构体的age设为String,再用parse::<i32>()转成数字。
方法二:通过serde_json::Value分步提取
无需定义临时结构体,先把JSON解析为通用Value类型,再手动提取字段并转换类型。性能略逊于方法一(需要二次解析字段),但灵活性更高。
代码示例:
use serde_json::Value; #[derive(Debug)] struct Name { name: String, } #[derive(Debug)] struct Age { age: i32, } fn main() -> Result<(), Box<dyn std::error::Error>> { let json_str = r#"{ "name": "John", "age": "30" }"#; // 解析为通用Value类型 let json_value: Value = serde_json::from_str(json_str)?; // 提取name字段构造Name结构体 let name_struct = Name { name: json_value["name"].as_str().ok_or("name字段不存在或非字符串类型")?.to_string(), }; // 提取age字段并转成i32,构造Age结构体 let age_struct = Age { age: json_value["age"].as_str().ok_or("age字段不存在或非字符串类型")?.parse()?, }; println!("{:?}", name_struct); println!("{:?}", age_struct); Ok(()) }
依赖配置
需要在Cargo.toml中添加以下依赖:
[dependencies] serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" # 使用方法一时需要添加: serde_aux = "1.0"
内容的提问来源于stack exchange,提问作者kh46r
相关产品推荐
相关产品推荐

