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

如何将JSON键提取为Rust结构体的字段值?

解决方案

方法一:使用 HashMap 转换(简单直观)

这种方法无需自定义反序列化逻辑,先将 JSON 反序列化为 HashMap,再转换为目标结构体列表:

  1. 定义不含 name 字段的辅助结构体,匹配 JSON 中的人员详情:
use serde::Deserialize;
use std::collections::HashMap;

#[derive(Debug, Deserialize)]
struct PersonDetails {
    pub age: u32,
    pub gender: Option<String>,
}
  1. 反序列化 JSON 为 HashMap,再转换为 Vec<Person>:
#[derive(Debug)]
pub struct Person {
    pub name: String,
    pub age: u32,
    pub gender: Option<String>,
}

// 示例 JSON 字符串
let json = r#"{
    "Bob": {
        "age": 41,
        "gender": "M"
    },
    "Alice": {
        "age": 34,
        "gender": "F"
    }
}"#;

// 反序列化为 HashMap
let person_map: HashMap<String, PersonDetails> = serde_json::from_str(json)?;

// 转换为 Vec<Person>
let people: Vec<Person> = person_map
    .into_iter()
    .map(|(name, details)| Person {
        name,
        age: details.age,
        gender: details.gender,
    })
    .collect();

此方法代码简洁易维护,缺点是需要额外的 HashMap 存储和转换步骤,大数据量场景下效率稍低。


方法二:自定义反序列化访问器(高效单步)

若追求更高效率,可实现自定义 Serde 访问器,直接将 JSON 映射转换为 Vec<Person>,无需中间结构:

  1. 修改 Person 结构体,标记 name 字段跳过反序列化(它来自 JSON 的键):
use serde::{Deserialize, Deserializer};
use serde::de::{Visitor, MapAccess};
use std::fmt;

#[derive(Debug, Deserialize)]
pub struct Person {
    #[serde(skip_deserializing)]
    pub name: String,
    pub age: u32,
    pub gender: Option<String>,
}
  1. 实现自定义访问器和反序列化逻辑:
struct PersonMapVisitor;

impl<'de> Visitor<'de> for PersonMapVisitor {
    type Value = Vec<Person>;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str("一个以姓名为键、人员详情为值的 JSON 对象")
    }

    fn visit_map<M>(self, mut map: M) -> Result<Self::Value, M::Error>
    where
        M: MapAccess<'de>,
    {
        let mut people = Vec::new();
        while let Some((name, mut person)) = map.next_entry::<String, Person>()? {
            person.name = name;
            people.push(person);
        }
        Ok(people)
    }
}

// 辅助函数:使用自定义访问器反序列化
fn deserialize_people<'de, D>(deserializer: D) -> Result<Vec<Person>, D::Error>
where
    D: Deserializer<'de>,
{
    deserializer.deserialize_map(PersonMapVisitor)
}
  1. 使用 DeserializeSeed 直接反序列化为 Vec<Person>(无需包装结构体):
struct PeopleSeed;

impl<'de> serde::de::DeserializeSeed<'de> for PeopleSeed {
    type Value = Vec<Person>;

    fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserialize_people(deserializer)
    }
}

// 反序列化示例
let deserializer = serde_json::Deserializer::from_str(json);
let people = PeopleSeed.deserialize(deserializer)?;

此方法单步完成反序列化,效率更高;缺点是需要编写更多自定义 Serde 代码,复杂度稍高。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 06:04:53