You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust中更优反序列化嵌套JSON对象的方案咨询

寻求更优的嵌套JSON反序列化方案

待反序列化的JSON对象:

{"name":"John Doe","age":43,"address":"{\"street\":\"10 Downing Street\",\"city\":\"London\"}"}

我目前用以下Rust代码实现了功能:

use serde_derive::{Deserialize, Serialize};
use serde_json::{Result, Value};

#[derive(Serialize, Deserialize)]
struct Person{
    name: String,
    address: Value
}

#[derive(Debug, Serialize, Deserialize)]
struct Address{
    street: String,
    city: String
}

impl From<Person> for Address{
    fn from(p: Person) -> Self {
        let str_val: String = serde_json::from_value(p.address).unwrap();
        let ad: Self =  serde_json::from_str(&str_val).unwrap();
        ad
    }
} 

fn main() -> Result<()> {
    let data = r#"{"name":"John Doe","age":43,"address":"{\"street\":\"10 Downing Street\",\"city\":\"London\"}"}"#;
    let p: Person = serde_json::from_str(data).unwrap();
    println!("{:?}", Address::from(p));

    Ok(())
}

但我觉得应该有更优的实现方式,请问有哪些改进建议?


改进建议

1. 自定义反序列化逻辑,一步完成转换

不需要先转成Value再二次解析,可以直接为Person结构体的address字段实现自定义反序列化,把字符串形式的JSON直接解析成Address类型,减少中间步骤,代码更简洁:

use serde::{Deserialize, Deserializer};
use serde_derive::{Deserialize, Serialize};
use serde_json::Result;

#[derive(Debug, Serialize, Deserialize)]
struct Person {
    name: String,
    age: u32,
    #[serde(deserialize_with = "deserialize_address")]
    address: Address,
}

#[derive(Debug, Serialize, Deserialize)]
struct Address {
    street: String,
    city: String,
}

// 自定义反序列化函数:把字符串转成Address
fn deserialize_address<'de, D>(deserializer: D) -> Result<Address, D::Error>
where
    D: Deserializer<'de>,
{
    let address_str: String = String::deserialize(deserializer)?;
    serde_json::from_str(&address_str).map_err(serde::de::Error::custom)
}

fn main() -> Result<()> {
    let data = r#"{"name":"John Doe","age":43,"address":"{\"street\":\"10 Downing Street\",\"city\":\"London\"}"}"#;
    let p: Person = serde_json::from_str(data)?;
    println!("{:?}", p.address);

    Ok(())
}

2. 避免使用unwrap(),优雅处理错误

原代码多次用unwrap(),一旦JSON格式错误会直接panic。改用?操作符传递错误,结合map_err转换错误类型,让程序能优雅处理解析失败的情况,符合Rust错误处理规范。

3. 合并不必要的结构体转换

如果只需要提取Address,可以直接通过临时结构体先取出address字段的字符串,再解析成Address,省去From转换的步骤:

use serde_json::Result;
use serde_derive::Deserialize;

#[derive(Debug, Deserialize)]
struct Address {
    street: String,
    city: String,
}

fn main() -> Result<()> {
    let data = r#"{"name":"John Doe","age":43,"address":"{\"street\":\"10 Downing Street\",\"city\":\"London\"}"}"#;
    // 临时结构体仅用于提取address字符串
    #[derive(Deserialize)]
    struct Temp { address: String }
    let temp: Temp = serde_json::from_str(data)?;
    let address: Address = serde_json::from_str(&temp.address)?;
    println!("{:?}", address);

    Ok(())
}

4. 补全字段,避免数据丢失

原代码的Person结构体未定义age字段,解析时会自动忽略这个字段,建议补上该字段,避免意外丢失JSON中的数据。


内容的提问来源于stack exchange,提问作者miimote

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 04:30:22