news 2026/4/16 7:48:13

【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/16 7:44:31

hcomm主机通信层 CPU-GPU数据同步与事件等待优化实战

作为一名摸爬滚打十几年的老码农&#xff0c;我见过太多因数据同步问题导致的性能瓶颈。今天咱们就深入CANN的hcomm主机通信层&#xff0c;扒一扒/hccl/hcomm/host_comm.cpp里那点事儿&#xff0c;特别是aclrtStreamWaitEvent这个关键角色的插入逻辑&#xff0c;看看如何玩转计…

作者头像 李华
网站建设 2026/4/16 7:45:04

从硬件加速到算法革新:进位保留乘法器的设计哲学与未来演进

从硬件加速到算法革新&#xff1a;进位保留乘法器的设计哲学与未来演进 在数字集成电路设计的浩瀚海洋中&#xff0c;乘法器始终扮演着核心角色。从早期的简单逻辑门实现&#xff0c;到如今面向AI加速器的高性能计算单元&#xff0c;乘法器的演进历程映射了整个半导体行业对性…

作者头像 李华
网站建设 2026/4/16 7:45:37

Zephyr RTOS线程调度策略与实践指南

1. Zephyr RTOS线程调度基础 在嵌入式开发中&#xff0c;实时操作系统&#xff08;RTOS&#xff09;的线程调度能力直接影响系统响应速度和资源利用率。Zephyr RTOS提供了三种核心调度策略&#xff1a;抢占式调度、协作式调度和时间片轮转调度。每种策略都有其独特的适用场景和…

作者头像 李华
网站建设 2026/3/18 6:10:17

C++之单例模式

文章目录饿汉式懒汉式单例模式(Singleton Pattern&#xff0c;也称为单件模式)&#xff0c;使用最广泛的设计模式之一。其意图是保证一个类仅有一个实例&#xff0c;并提供一个访问它的全局访问点&#xff0c;该实例被所有程序模块共享面向对象编程中&#xff0c;每个对象都应该…

作者头像 李华
网站建设 2026/4/11 13:47:25

RAG大模型智能客服:从架构设计到生产环境部署的实战指南

背景痛点&#xff1a;传统客服的“老毛病” 做ToB客服的同学都懂&#xff0c;最怕的不是用户问题多&#xff0c;而是“知识库又过期了”。 规则引擎&#xff1a;写一条规则要三天&#xff0c;用户换种问法就“404”&#xff1b;纯生成式LLM&#xff1a;满嘴跑火车&#xff0c…

作者头像 李华
网站建设 2026/4/16 1:20:34

基于CompVis SVD基础模型的图生视频效率优化实战

基于CompVis SVD基础模型的图生视频效率优化实战 摘要&#xff1a;本文针对CompVis SVD基础模型在图像生成视频任务中的计算效率瓶颈&#xff0c;提出一套完整的优化方案。通过模型量化、显存优化和流水线并行等技术&#xff0c;在保证生成质量的前提下显著提升推理速度。读者将…

作者头像 李华