news 2026/4/18 9:08:14

【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/18 5:41:57

实战解析:如何高效处理 ccopt report latency 的 report 机制

实战解析&#xff1a;如何高效处理 ccopt report latency 的 report 机制 摘要&#xff1a;在分布式系统中&#xff0c;ccopt report latency 的 report 机制常常面临高延迟和数据不一致的挑战。本文深入分析 ccopt report latency 的核心问题&#xff0c;提供一套基于异步批处…

作者头像 李华
网站建设 2026/4/18 8:03:12

基于DeepSeek大模型的智能客服系统:如何提升响应效率与并发处理能力

基于DeepSeek大模型的智能客服系统&#xff1a;如何提升响应效率与并发处理能力 传统客服系统最怕“人多嘴杂”——促销当天一涌而入&#xff0c;人工坐席全忙&#xff0c;机器人却卡在正则里转圈。本文记录我们如何用 DeepSeek 把峰值 QPS 从 120 提到 1800&#xff0c;同时把…

作者头像 李华
网站建设 2026/4/18 7:01:55

C++之静态成员

C为什么需要静态成员C语言中可以通过全局变量实现数据共享&#xff0c;在程序的任何位置都可以访问C中希望某个类的多个对象之间实现数据共享&#xff0c;可以通过static建立一个被局限在类中使用的全局资源&#xff0c;该类型资源被称为静态成员 静态成员变量 静态成员变量&…

作者头像 李华
网站建设 2026/4/18 9:38:03

引脚统计背后的设计哲学:AD21原理图可维护性深度解析

引脚统计背后的设计哲学&#xff1a;AD21原理图可维护性深度解析 在硬件设计领域&#xff0c;原理图的可维护性往往决定了项目后期的迭代效率与团队协作的流畅度。当我们面对一个包含数千个元器件的复杂系统时&#xff0c;如何快速评估设计复杂度、预测潜在风险并优化团队协作…

作者头像 李华
网站建设 2026/4/18 5:44:38

ChatTTS库深度解析:从文本到语音的高效转换实践

ChatT 落地词&#xff1a;chattts库 从哪个角度论述&#xff1a;技术科普 标题&#xff1a;ChatTTS库深度解析&#xff1a;从文本到语音的高效转换实践 摘要&#xff1a;在开发语音交互应用时&#xff0c;如何实现高效、自然的文本到语音转换是开发者面临的常见挑战。本文深入解…

作者头像 李华
网站建设 2026/4/18 8:31:13

基于C语言的毕业设计实战:从嵌入式数据采集系统到可维护代码架构

基于C语言的毕业设计实战&#xff1a;从嵌入式数据采集系统到可维护代码架构 摘要&#xff1a;许多计算机专业学生在完成“基于C语言的毕业设计”时&#xff0c;常陷入功能堆砌、缺乏工程规范的困境。本文以一个真实的嵌入式数据采集系统为案例&#xff0c;展示如何通过模块化设…

作者头像 李华