You need to enable JavaScript to run this app. C#使用Newtonsoft.Json反序列化动态键JSON并提取数据存SQL的方法
优惠活动
大模型
产品
解决方案
定价
更多

C#使用Newtonsoft.Json反序列化动态键JSON并提取数据存SQL的方法

动态键JSON反序列化与结构化存库实现方法

问题本质

你之前尝试用json.result.inside.????.alt的点号路径无法取值,是因为result.inside下的子节点键名是无固定规则的动态字符串(比如示例中的MMLEHH-YUR、OZWVHR-N3ED4-CM3ACG),不存在和C#固定属性名的匹配关系,根本无法通过写死的点语法访问到具体节点。
Newtonsoft.Json反序列化得到的dynamic对象实际类型是JObject,本身支持以键值对方式遍历所有动态属性,不需要提前获知具体键名。

  • 如果已经提前确定某个固定键名,也可以通过索引器语法灵活取值,比如insideNode["MMLEHH-YUR"]["alt"],但接口返回的键是动态变化时,这种方式不再适用,必须遍历所有属性节点。

实现步骤

1. 定义匹配存储需求的强类型结构

按照你期望的字段格式,定义对应的数据类,后续可直接和SQL表字段做映射,避免运行时拆包引发的类型错误:

/// <summary>映射到SQL表的结构化数据类</summary>
public class SqlTargetRecord
{
    /// <summary>对应动态键名,如 MMLEHH-YUR</summary>
    public string Global { get; set; }
    public object Id { get; set; }
    public int Number { get; set; }
    public string Alt { get; set; }
    public decimal Price { get; set; }
    public decimal Price2 { get; set; }
    public string State { get; set; }
    public string Vol { get; set; }
    public string Misc { get; set; }
}

2. 遍历动态节点提取结构化数据

不需要写死每个动态键的访问路径,直接遍历inside节点下的所有属性,逐笔提取字段值:

using Newtonsoft.Json.Linq;
using System.Collections.Generic;

// 解析接口返回的JSON字符串
JObject fullJson = JObject.Parse(jsonResponse);
var recordList = new List<SqlTargetRecord>();

// 定位到 result > inside 节点
JObject insideNode = fullJson["result"]?["inside"] as JObject;
if (insideNode == null) return;

// 遍历inside下所有动态命名的键值对
foreach (JProperty itemProp in insideNode.Properties())
{
    // 键名就是需要存入Global字段的值
    string globalKeyValue = itemProp.Name;
    // 键对应的对象值就是包含业务字段的节点
    JObject itemDataNode = itemProp.Value as JObject;
    if (itemDataNode == null) continue;

    // 逐字段映射到强类型结构
    var currentRecord = new SqlTargetRecord
    {
        Global = globalKeyValue,
        Id = itemDataNode["id"]?.ToObject<object>(),
        Number = itemDataNode["number"]?.ToObject<int>() ?? 0,
        Alt = itemDataNode["alt"]?.ToObject<string>(),
        Price = itemDataNode["descr"]?["price"]?.ToObject<decimal>() ?? 0,
        Price2 = itemDataNode["descr"]?["price2"]?.ToObject<decimal>() ?? 0,
        State = itemDataNode["descr"]?["state"]?.ToObject<string>(),
        Vol = itemDataNode["vol"]?.ToObject<string>(),
        Misc = itemDataNode["misc"]?.ToObject<string>()
    };

    recordList.Add(currentRecord);
}

注意事项

  • 提取阶段就完成类型转换,比如把JSON里字符串格式的价格(如"4.33000")直接转成SQL支持的decimal类型,避免存库时出现类型不匹配错误。
  • 提取完成后得到的recordList是标准强类型集合,可以直接配合ADO.NET、Dapper、EF Core等数据访问组件,逐笔写入SQL数据库,不需要再处理dynamic对象的拆包逻辑。
  • 所有节点取值时必须加空值判断,避免接口返回字段缺失时触发空引用异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.25 05:45:10