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

如何使用Serde JSON处理JSON顶层动态键名问题

解决Rust中JSON顶层动态键名的问题

针对你遇到的顶层动态键(如Time Series (5min),其中时间间隔动态变化)的问题,以下是两种实用解决方案:

前提准备

先明确你的JSON结构和基础结构体定义(模拟示例):

示例JSON

{
  "Meta Data": {
    "1. Information": "Intraday (5min) open, high, low, close prices",
    "2. Symbol": "IBM",
    "3. Last Refreshed": "2024-05-20 16:00:00",
    "4. Interval": "5min",
    "5. Output Size": "Compact",
    "6. Time Zone": "US/Eastern"
  },
  "Time Series (5min)": {
    "2024-05-20 16:00:00": {
      "1. open": "150.00",
      "2. high": "150.50",
      "3. low": "149.80",
      "4. close": "150.20",
      "5. volume": "10000"
    }
  }
}

基础结构体

use serde::Deserialize;
use std::collections::HashMap;

#[derive(Deserialize, Debug)]
struct MetaData {
    #[serde(rename = "1. Information")]
    information: String,
    #[serde(rename = "2. Symbol")]
    symbol: String,
    #[serde(rename = "3. Last Refreshed")]
    last_refreshed: String,
    #[serde(rename = "4. Interval")]
    interval: String,
    #[serde(rename = "5. Output Size")]
    output_size: String,
    #[serde(rename = "6. Time Zone")]
    time_zone: String,
}

#[derive(Deserialize, Debug)]
struct PriceData {
    #[serde(rename = "1. open")]
    open: String,
    #[serde(rename = "2. high")]
    high: String,
    #[serde(rename = "3. low")]
    low: String,
    #[serde(rename = "4. close")]
    close: String,
    #[serde(rename = "5. volume")]
    volume: String,
}

方案一:自定义反序列化(推荐)

通过实现Deserialize trait,将动态键的解析逻辑封装起来,直接解析为类型安全的结构体:

#[derive(Debug)]
struct StockData {
    meta_data: MetaData,
    interval: String,
    time_series: HashMap<String, PriceData>,
}

impl<'de> Deserialize<'de> for StockData {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        // 将整个JSON解析为HashMap,处理动态键
        let mut map: HashMap<String, serde_json::Value> = HashMap::deserialize(deserializer)?;
        
        // 提取并解析元数据
        let meta_data_value = map.remove("Meta Data")
            .ok_or_else(|| serde::de::Error::missing_field("Meta Data"))?;
        let meta_data: MetaData = serde_json::from_value(meta_data_value)?;
        
        // 匹配以"Time Series ("开头的动态键
        let (time_series_key, time_series_value) = map.into_iter()
            .find(|(key, _)| key.starts_with("Time Series ("))
            .ok_or_else(|| serde::de::Error::missing_field("Time Series (*)"))?;
        
        // 提取时间间隔(如从"Time Series (5min)"中取出"5min")
        let interval = time_series_key.strip_prefix("Time Series (")
            .and_then(|s| s.strip_suffix(")"))
            .ok_or_else(|| serde::de::Error::custom("Invalid time series key format"))?
            .to_string();
        
        // 解析时间序列数据
        let time_series: HashMap<String, PriceData> = serde_json::from_value(time_series_value)?;
        
        Ok(Self {
            meta_data,
            interval,
            time_series,
        })
    }
}

// 使用示例
fn main() -> Result<(), Box<dyn std::error::Error>> {
    let json_str = r#"[你的JSON字符串]"#;
    let stock_data: StockData = serde_json::from_str(json_str)?;
    println!("{:#?}", stock_data);
    Ok(())
}

方案二:手动解析HashMap(快速原型)

如果不想写自定义反序列化,可以先将JSON解析为HashMap<String, serde_json::Value>,再手动提取并转换数据:

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let json_str = r#"[你的JSON字符串]"#;
    
    // 解析为原始HashMap
    let raw_map: HashMap<String, serde_json::Value> = serde_json::from_str(json_str)?;
    
    // 解析元数据
    let meta_data: MetaData = serde_json::from_value(raw_map["Meta Data"].clone())?;
    
    // 查找时间序列动态键
    let time_series_key = raw_map.keys()
        .find(|k| k.starts_with("Time Series ("))
        .ok_or("No time series key found")?;
    
    // 解析时间序列数据
    let time_series: HashMap<String, PriceData> = serde_json::from_value(raw_map[time_series_key].clone())?;
    
    println!("Meta Data: {:#?}", meta_data);
    println!("Time Series ({}): {:#?}", meta_data.interval, time_series);
    
    Ok(())
}

依赖配置

确保Cargo.toml中添加serde相关依赖:

[dependencies]
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 20:15:17