如何在C# .NET中解析结构不固定的JSON数据?
C# .NET解析动态Key JSON的最佳方式
你的JSON特点是data字段下的键是动态数字,且子对象的属性不固定,没法直接用强类型模型映射,推荐以下几种实用方案:
方案1:使用.NET内置的System.Text.Json
适合.NET Core 3.0+、.NET 5+版本,无需额外安装包:
实现步骤:
- 按行拆分输入的JSON内容(因为示例是多行独立JSON结构)
- 用
JsonNode(灵活的动态JSON节点)或Dictionary<string, JsonElement>解析每行内容
示例代码:
using System.Text.Json; using System.Text.Json.Nodes; // 假设你的JSON内容是多行字符串 string jsonContent = @"{""data"":{""5"":{""isDeleted"":""false"",""day"":""THU""}},""action"":""edit""} {""data"":{""7"":{""isDeleted"":""false"",""name"":""alex""}},""action"":""edit""} {""data"":{""90"":{""isDeleted"":""true"",""job"":""software""}},""action"":""edit""}"; // 按行拆分并过滤空行 string[] jsonLines = jsonContent.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); foreach (string line in jsonLines) { // 解析为可动态访问的JsonNode JsonNode root = JsonNode.Parse(line)!; // 获取固定的action字段 string action = root["action"]!.GetValue<string>(); // 遍历data下的动态key JsonNode dataNode = root["data"]!; foreach (var kvp in dataNode.AsObject()) { string dynamicKey = kvp.Key; // 对应"5"、"7"、"90"这类动态键 JsonNode item = kvp.Value; // 获取公共字段isDeleted string isDeleted = item["isDeleted"]!.GetValue<string>(); // 按需获取其他动态字段 if (item["day"] is not null) { string day = item["day"]!.GetValue<string>(); Console.WriteLine($"动态键: {dynamicKey}, 操作: {action}, 是否删除: {isDeleted}, 星期: {day}"); } else if (item["name"] is not null) { string name = item["name"]!.GetValue<string>(); Console.WriteLine($"动态键: {dynamicKey}, 操作: {action}, 是否删除: {isDeleted}, 姓名: {name}"); } else if (item["job"] is not null) { string job = item["job"]!.GetValue<string>(); Console.WriteLine($"动态键: {dynamicKey}, 操作: {action}, 是否删除: {isDeleted}, 职业: {job}"); } } }
方案2:使用Newtonsoft.Json(Json.NET)
如果项目已经依赖这个第三方库,用它处理动态结构会更简洁:
示例代码:
using Newtonsoft.Json.Linq; string jsonContent = @"{""data"":{""5"":{""isDeleted"":""false"",""day"":""THU""}},""action"":""edit""} {""data"":{""7"":{""isDeleted"":""false"",""name"":""alex""}},""action"":""edit""} {""data"":{""90"":{""isDeleted"":""true"",""job"":""software""}},""action"":""edit""}"; string[] jsonLines = jsonContent.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); foreach (string line in jsonLines) { JObject root = JObject.Parse(line); string action = root["action"]!.Value<string>(); JObject dataObj = (JObject)root["data"]!; foreach (var kvp in dataObj) { string dynamicKey = kvp.Key; JToken item = kvp.Value; string isDeleted = item["isDeleted"]!.Value<string>(); if (item["day"] != null) { string day = item["day"].Value<string>(); Console.WriteLine($"动态键: {dynamicKey}, 操作: {action}, 是否删除: {isDeleted}, 星期: {day}"); } else if (item["name"] != null) { string name = item["name"].Value<string>(); Console.WriteLine($"动态键: {dynamicKey}, 操作: {action}, 是否删除: {isDeleted}, 姓名: {name}"); } else if (item["job"] != null) { string job = item["job"].Value<string>(); Console.WriteLine($"动态键: {dynamicKey}, 操作: {action}, 是否删除: {isDeleted}, 职业: {job}"); } } }
方案3:强类型+动态字典结合
如果isDeleted是固定公共字段,其他字段动态,可以用这种方式兼顾类型安全和灵活性:
using System.Text.Json; // 定义包含公共字段的模型,用字典存动态字段 public class BaseDataItem { public string isDeleted { get; set; } [JsonExtensionData] public Dictionary<string, JsonElement> ExtraFields { get; set; } = new(); } public class JsonRoot { public Dictionary<string, BaseDataItem> data { get; set; } public string action { get; set; } } // 解析示例 string sampleLine = @"{""data"":{""5"":{""isDeleted"":""false"",""day"":""THU""}},""action"":""edit""}"; JsonRoot root = JsonSerializer.Deserialize<JsonRoot>(sampleLine)!; foreach (var kvp in root.data) { string dynamicKey = kvp.Key; BaseDataItem item = kvp.Value; Console.WriteLine($"动态键: {dynamicKey}, 操作: {root.action}, 是否删除: {item.isDeleted}"); // 尝试获取动态字段day if (item.ExtraFields.TryGetValue("day", out JsonElement dayElem)) { string day = dayElem.GetString()!; Console.WriteLine($"星期: {day}"); } }
内容的提问来源于stack exchange,提问作者Perusing
相关产品推荐
相关产品推荐

