news 2026/4/28 2:44:41

【C#】JsonConvert实战:从基础解析到复杂数据结构处理

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【C#】JsonConvert实战:从基础解析到复杂数据结构处理

1. JsonConvert基础入门:从零开始处理JSON数据

第一次接触JSON数据处理时,我完全被各种花括号和方括号搞晕了。后来发现C#中的JsonConvert简直就是处理JSON的神器,它属于Newtonsoft.Json库(现在也叫Json.NET),是目前.NET生态中最流行的JSON处理工具。

安装它只需要在NuGet包管理器中搜索"Newtonsoft.Json",或者通过命令行:

Install-Package Newtonsoft.Json

基础用法简单到令人发指。比如有个用户数据:

{ "name": "张三", "age": 25, "isVIP": true }

用三行代码就能转换成对象:

using Newtonsoft.Json; string json = "{\"name\":\"张三\",\"age\":25,\"isVIP\":true}"; User user = JsonConvert.DeserializeObject<User>(json); Console.WriteLine($"用户名:{user.Name}");

这里的User类长这样:

public class User { public string Name { get; set; } public int Age { get; set; } public bool IsVIP { get; set; } }

反过来把对象转JSON更简单:

User newUser = new User { Name = "李四", Age = 30, IsVIP = false }; string newJson = JsonConvert.SerializeObject(newUser); Console.WriteLine(newJson); // 输出:{"Name":"李四","Age":30,"IsVIP":false}

2. 实战解析复杂JSON结构

2.1 处理嵌套对象

实际项目中遇到的JSON很少像上面那么简单。比如电商平台的订单数据:

{ "orderId": "20230615001", "customer": { "name": "王五", "phone": "13800138000" }, "items": [ { "productId": "P1001", "quantity": 2 }, { "productId": "P1005", "quantity": 1 } ] }

对应的C#类结构:

public class Order { public string OrderId { get; set; } public Customer Customer { get; set; } public List<OrderItem> Items { get; set; } } public class Customer { public string Name { get; set; } public string Phone { get; set; } } public class OrderItem { public string ProductId { get; set; } public int Quantity { get; set; } }

解析代码依然简洁:

Order order = JsonConvert.DeserializeObject<Order>(jsonString); Console.WriteLine($"订单包含{order.Items.Count}件商品");

2.2 动态解析与JObject

有时候我们不想定义完整的类结构,或者JSON结构不固定,可以用JObject动态解析:

JObject jObj = JObject.Parse(jsonString); string customerName = (string)jObj["customer"]["name"]; JArray items = (JArray)jObj["items"]; int totalQuantity = items.Sum(item => (int)item["quantity"]);

动态解析特别适合处理第三方API返回的不规则数据。比如有个天气API返回:

{ "status": "ok", "data": { "temperature": 26, "humidity": 0.78, "extra": { "wind_speed": 3.2, "visibility": "good" } } }

我们可以只提取需要的字段:

var weather = JObject.Parse(weatherJson); if ((string)weather["status"] == "ok") { double temp = (double)weather["data"]["temperature"]; string visibility = (string)weather["data"]["extra"]["visibility"]; }

3. 高级技巧与性能优化

3.1 自定义序列化设置

JsonConvert提供了丰富的配置选项。比如格式化输出、处理空值、日期格式等:

JsonSerializerSettings settings = new JsonSerializerSettings { Formatting = Formatting.Indented, // 美化输出 NullValueHandling = NullValueHandling.Ignore, // 忽略null值 DateFormatString = "yyyy-MM-dd HH:mm:ss" // 日期格式 }; string prettyJson = JsonConvert.SerializeObject(order, settings);

3.2 处理特殊类型

遇到DateTime、Guid等特殊类型时,默认序列化可能不符合需求。我们可以自定义转换器:

public class CustomDateTimeConverter : JsonConverter<DateTime> { public override DateTime ReadJson(JsonReader reader, Type type, DateTime existing, bool hasValue, JsonSerializer serializer) { return DateTime.ParseExact(reader.Value.ToString(), "yyyy-MM-dd", CultureInfo.InvariantCulture); } public override void WriteJson(JsonWriter writer, DateTime value, JsonSerializer serializer) { writer.WriteValue(value.ToString("yyyy-MM-dd")); } } // 使用自定义转换器 JsonConvert.SerializeObject(order, new CustomDateTimeConverter());

3.3 性能优化建议

处理大量JSON数据时,这几个技巧可以提升性能:

  1. 重用JsonSerializerSettings实例
  2. 对于只读操作,使用JsonTextReader直接流式读取
  3. 使用内存池减少GC压力
// 流式读取大文件 using (StreamReader file = File.OpenText("large.json")) using (JsonTextReader reader = new JsonTextReader(file)) { while (reader.Read()) { if (reader.TokenType == JsonToken.StartObject) { JObject obj = JObject.Load(reader); // 处理单个对象 } } }

4. 实战案例:电商平台订单处理系统

假设我们要开发一个订单处理系统,需要处理这样的订单数据:

{ "orderId": "ORDER_12345", "createTime": "2023-06-15T14:30:00", "status": "paid", "products": [ { "sku": "SKU1001", "name": "无线鼠标", "price": 129.9, "specs": { "color": "black", "weight": 0.2 } }, { "sku": "SKU2003", "name": "机械键盘", "price": 399.0, "specs": { "color": "silver", "weight": 1.2, "switchType": "red" } } ], "payment": { "method": "alipay", "amount": 528.9, "transactionId": "ALI123456789" }, "delivery": { "address": "北京市海淀区", "receiver": "张三", "phone": "13800138000" } }

首先定义对应的类结构:

public class Order { public string OrderId { get; set; } public DateTime CreateTime { get; set; } public string Status { get; set; } public List<Product> Products { get; set; } public PaymentInfo Payment { get; set; } public DeliveryInfo Delivery { get; set; } } public class Product { public string Sku { get; set; } public string Name { get; set; } public decimal Price { get; set; } public Dictionary<string, object> Specs { get; set; } } public class PaymentInfo { public string Method { get; set; } public decimal Amount { get; set; } public string TransactionId { get; set; } } public class DeliveryInfo { public string Address { get; set; } public string Receiver { get; set; } public string Phone { get; set; } }

处理逻辑示例:

// 解析订单 Order order = JsonConvert.DeserializeObject<Order>(orderJson); // 计算订单总价 decimal total = order.Products.Sum(p => p.Price); bool priceValid = total == order.Payment.Amount; // 检查特殊商品 bool hasHeavyProduct = order.Products.Any(p => p.Specs.ContainsKey("weight") && Convert.ToDecimal(p.Specs["weight"]) > 1.0); // 生成简化的物流信息 var shippingInfo = new { OrderId = order.OrderId, Receiver = order.Delivery.Receiver, Phone = order.Delivery.Phone.Substring(0, 3) + "****" + order.Delivery.Phone.Substring(7), ProductCount = order.Products.Count }; string shippingJson = JsonConvert.SerializeObject(shippingInfo);

5. 常见问题排查与调试技巧

5.1 类型不匹配问题

最常见的错误是JSON中的类型与C#属性类型不匹配。比如JSON中是字符串"123",但C#属性是int。解决方法:

// 错误示例 public class WrongExample { public int Age { get; set; } // JSON中是"age":"25"会报错 } // 正确做法:使用JsonProperty指定名称,并确保类型兼容 public class CorrectExample { [JsonProperty("age")] public int Age { get; set; } }

5.2 处理多态类型

当JSON中的对象可能是多种类型时,可以用TypeNameHandling:

var settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto }; string json = JsonConvert.SerializeObject(obj, settings); var result = JsonConvert.DeserializeObject<BaseType>(json, settings);

5.3 调试技巧

当JSON解析出错时,可以这样排查:

  1. 先用JToken.Parse验证JSON格式是否正确
  2. 使用JsonConvert.PopulateObject逐步填充对象
  3. 实现错误处理:
try { var obj = JsonConvert.DeserializeObject<MyType>(json); } catch (JsonException ex) { Console.WriteLine($"解析失败:{ex.Message}"); Console.WriteLine($"错误位置:{ex.Path}"); Console.WriteLine($"原始JSON片段:{json.Substring(ex.LinePosition - 20, 40)}"); }

6. 最佳实践与性能对比

6.1 JsonConvert vs System.Text.Json

.NET Core 3.0引入了System.Text.Json,性能更好但功能较少。对比选择:

特性JsonConvertSystem.Text.Json
性能中等
功能丰富基础
自定义灵活有限
依赖第三方官方内置

迁移建议:新项目可以考虑System.Text.Json,现有项目继续用JsonConvert更稳妥。

6.2 内存优化技巧

处理大JSON文件时:

  1. 使用StreamReader避免全量读取
  2. 选择合适的数据结构(如Dictionary代替JObject)
  3. 禁用不必要的特性(如注释、元数据)
var settings = new JsonSerializerSettings { MetadataPropertyHandling = MetadataPropertyHandling.Ignore };

6.3 安全注意事项

  1. 始终验证外部JSON数据
  2. 限制最大解析深度(MaxDepth)
  3. 处理循环引用:
settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;

7. 真实项目经验分享

在最近的一个物联网项目中,我们需要处理设备上报的JSON数据。设备数据格式复杂且经常变化,我们最终采用了这样的方案:

  1. 基础信息用强类型类解析
  2. 动态扩展字段用JObject处理
  3. 自定义转换器处理特殊格式
public class DeviceData { public string DeviceId { get; set; } public DateTime Timestamp { get; set; } [JsonExtensionData] public IDictionary<string, JToken> ExtendedData { get; set; } } // 处理未知字段 if (data.ExtendedData.TryGetValue("voltage", out var voltageToken)) { double voltage = voltageToken.Value<double>(); }

遇到的一个坑是设备时间格式不统一,解决方案是写个灵活的时间解析器:

public class FlexibleDateTimeConverter : JsonConverter<DateTime> { private static readonly string[] formats = { "yyyy-MM-ddTHH:mm:ss", "yyyy/MM/dd HH:mm:ss", "yyyyMMddHHmmss" }; public override DateTime ReadJson(/* 参数 */) { string dateString = reader.Value.ToString(); foreach (var format in formats) { if (DateTime.TryParseExact(dateString, format, null, DateTimeStyles.None, out var result)) { return result; } } return DateTime.Parse(dateString); // 最后尝试默认解析 } }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/22 18:43:57

ops-nn卷积深潜 Winograd分块与L1缓存命中率优化

摘要 本文深入解析CANN项目中ops-nn算子库的卷积优化技术&#xff0c;重点聚焦conv2d_tiling.cpp中的Winograd分块策略。通过逐行分析get_tiling_strategy()函数&#xff0c;揭示如何通过智能分块提升L1缓存命中率&#xff0c;并在Stable Diffusion UNet网络中实现Conv2D操作显…

作者头像 李华
网站建设 2026/4/25 23:27:08

ops-math GEMM攻坚 矩阵分块与NPU Cube单元协同

&#x1f4d6; 摘要 本文深入解析CANN项目中ops-math GEMM算子在NPU上的高性能实现奥秘。以LLaMA-7B模型中的MatMul算子为实战案例&#xff0c;重点剖析block_m、block_n、block_k等关键分块参数对计算吞吐量的影响规律。通过大量实测数据验证不同batch_size下的最优分块配置&…

作者头像 李华
网站建设 2026/4/25 23:27:10

AI辅助开发实战:电子科学与技术毕设中的智能系统设计与工程化落地

AI辅助开发实战&#xff1a;电子科学与技术毕设中的智能系统设计与工程化落地 1. 毕设开发中的典型痛点 电子科学与技术方向的毕设&#xff0c;往往要求“软硬协同”&#xff1a;既要跑通算法&#xff0c;又要能在板子上实时演示。真正动手才知道&#xff0c;下面这几座大山几…

作者头像 李华
网站建设 2026/4/19 16:41:35

AI 辅助下的商城开发毕业设计:从需求建模到代码生成的全流程实战

AI 辅助下的商城开发毕业设计&#xff1a;从需求建模到代码生成的全流程实战 毕业设计只剩 8 周&#xff0c;导师一句“功能要完整、代码要优雅、答辩要能打”&#xff0c;直接把难度拉满。 去年我还在手写 SQL、通宵调接口&#xff0c;今年直接让 AI 打主力&#xff0c;三周跑…

作者头像 李华