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

Rust下无需枚举全量变体的动态键JSON API响应建模方案

实现方案

你遇到的是JSON顶层键为动态值的场景,不需要枚举所有股票代码作为枚举变体,serde原生支持将任意键的JSON对象反序列化为HashMap,在此基础上可以灵活实现强类型封装:


基础实现方案

直接用HashMap承载动态股票代码和动态货币的映射关系,不需要调整结构即可兼容新增的股票/货币类型:

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

// 内层结构:货币代码 -> 价格,货币为动态值时直接用HashMap
type CurrencyPrice = HashMap<String, f64>;

// 外层结构:股票代码 -> 对应价格结构,股票为动态值时用HashMap承载
#[derive(Debug, Deserialize)]
#[serde(transparent)]
pub struct PriceResponse(pub HashMap<String, CurrencyPrice>);

反序列化使用示例:

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let json_resp = r#"{"AAPL": {"usd": 10}, "GOOG": {"usd": 20}, "TSLA": {"usd": 30}}"#;
    let price_resp: PriceResponse = serde_json::from_str(json_resp)?;

    // 直接获取指定股票的美元价格
    if let Some(aapl_usd) = price_resp.0.get("AAPL").and_then(|p| p.get("usd")) {
        println!("AAPL 价格:{} USD", aapl_usd);
    }

    Ok(())
}

语义化封装优化

可以为结构体添加辅助方法,隐藏内部HashMap实现细节,提升易用性:

impl PriceResponse {
    /// 获取指定股票、指定货币的价格
    pub fn get(&self, stock_code: &str, currency: &str) -> Option<f64> {
        self.0.get(stock_code)?.get(currency).copied()
    }

    /// 遍历所有股票价格
    pub fn iter(&self) -> impl Iterator<Item = (&String, &CurrencyPrice)> {
        self.0.iter()
    }
}

// 调用示例
let tsla_price = price_resp.get("TSLA", "usd").unwrap_or_default();

可选优化(金融精度场景)

如果对价格精度要求高,避免浮点数精度误差,可以将价格类型替换为十进制类型:

  • 引入依赖:rust_decimal = { version = "1.30", features = ["serde-float"] }
  • 将CurrencyPrice定义改为type CurrencyPrice = HashMap<String, rust_decimal::Decimal>;即可直接适配反序列化,不需要修改其他逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.21 10:24:03