1. .NET对象转JSON的常见场景与需求
在.NET开发中,对象与JSON之间的转换几乎是每个开发者都会遇到的日常任务。无论是Web API的响应、前端数据交互,还是配置文件处理,JSON作为轻量级的数据交换格式都扮演着关键角色。我见过太多项目因为JSON序列化性能问题导致接口响应缓慢,也遇到过因为格式不规范引发的客户端解析错误。这些问题往往源于对.NET序列化机制理解不够深入。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 基础序列化方案:Json.NET (Newtonsoft.Json)
2.1 基本使用方法
Json.NET(现称Newtonsoft.Json)长期以来都是.NET生态中的事实标准。安装NuGet包后,基础用法简单直接:
csharp复制using Newtonsoft.Json;
var product = new Product { Id = 1, Name = "Laptop" };
string json = JsonConvert.SerializeObject(product);
// 输出: {"Id":1,"Name":"Laptop"}
Product deserialized = JsonConvert.DeserializeObject<Product>(json);
2.2 高级配置选项
实际项目中我们通常需要更多控制:
csharp复制var settings = new JsonSerializerSettings {
NullValueHandling = NullValueHandling.Ignore,
DateFormatString = "yyyy-MM-ddTHH:mm:ss",
ContractResolver = new CamelCasePropertyNamesContractResolver()
};
string json = JsonConvert.SerializeObject(product, settings);
重要提示:DateFormatString的格式选择直接影响前后端对接,我曾遇到因时区格式不匹配导致的生产事故
2.3 性能优化技巧
- 复用JsonSerializerSettings实例
- 对于大型对象集合,考虑使用JsonTextWriter进行流式处理
- 启用Bson格式可获得约15%的性能提升(适合内部系统通信)
3. 官方方案:System.Text.Json
3.1 基本序列化
.NET Core 3.0引入的System.Text.Json在性能上有显著优势:
csharp复制using System.Text.Json;
var options = new JsonSerializerOptions {
WriteIndented = true,
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
};
string json = JsonSerializer.Serialize(product, options);
Product deserialized = JsonSerializer.Deserialize<Product>(json);
3.2 与Newtonsoft.Json的主要差异
- 默认严格区分大小写
- 不支持动态类型(dynamic)
- 日期格式处理更严格
- 默认不序列化私有字段
3.3 性能对比
在我的基准测试中(序列化10,000个复杂对象):
- System.Text.Json比Newtonsoft.Json快约1.8倍
- 内存分配减少约30%
- 对于ASP.NET Core应用,切换后API吞吐量提升明显
4. 二进制JSON方案:MessagePack
4.1 基本使用
当需要极致性能时,MessagePack是不二之选:
csharp复制using MessagePack;
[MessagePackObject]
public class Product {
[Key(0)]
public int Id { get; set; }
[Key(1)]
public string Name { get; set; }
}
byte[] bytes = MessagePackSerializer.Serialize(product);
Product obj = MessagePackSerializer.Deserialize<Product>(bytes);
4.2 适用场景
- 微服务间高性能通信
- 游戏开发中的网络传输
- 需要持久化大量数据的场景
实测数据:相比JSON,MessagePack序列化速度快3-5倍,体积小40-60%
5. 特殊场景解决方案
5.1 循环引用处理
处理对象图时循环引用是常见痛点:
csharp复制// Newtonsoft.Json
settings.ReferenceLoopHandling = ReferenceLoopHandling.Serialize;
settings.PreserveReferencesHandling = PreserveReferencesHandling.Objects;
// System.Text.Json
options.ReferenceHandler = ReferenceHandler.Preserve;
5.2 多态类型序列化
处理继承体系时需要特殊配置:
csharp复制[JsonDerivedType(typeof(Student), typeDiscriminator: "student")]
[JsonDerivedType(typeof(Teacher), typeDiscriminator: "teacher")]
public class Person { ... }
6. 实战经验与性能调优
6.1 缓存序列化器实例
避免重复创建JsonSerializerOptions/JsonSerializerSettings:
csharp复制// 最佳实践
private static readonly JsonSerializerOptions _options = new() { ... };
6.2 流式处理大型JSON
对于超过100MB的JSON数据,务必使用流式API:
csharp复制await using var stream = new MemoryStream();
await JsonSerializer.SerializeAsync(stream, largeCollection);
6.3 自定义转换器
处理特殊类型时创建自定义转换器:
csharp复制public class DateTimeOffsetConverter : JsonConverter<DateTimeOffset> {
public override DateTimeOffset Read(...) { ... }
public override void Write(...) { ... }
}
7. 各方案选型指南
| 特性 | Newtonsoft.Json | System.Text.Json | MessagePack |
|---|---|---|---|
| 成熟度 | 高 | 中 | 高 |
| 性能 | 中等 | 高 | 极高 |
| 功能完整性 | 非常全面 | 基础功能 | 特殊格式 |
| 内存效率 | 中等 | 高 | 极高 |
| 学习曲线 | 低 | 低 | 中 |
| 最佳场景 | 遗留系统 | 新.NET项目 | 高性能需求 |
在最近的一个电商平台项目中,我们根据不同场景混合使用这些方案:
- Web API响应使用System.Text.Json
- 后台任务间的消息传递使用MessagePack
- 与第三方系统集成时保持Newtonsoft.Json兼容性
8. 常见问题排查
-
日期格式不一致:
- 解决方案:明确指定DateTime格式
csharp复制options.Converters.Add(new DateTimeConverter("yyyy-MM-dd HH:mm:ss")); -
大小写敏感问题:
- System.Text.Json默认区分大小写
- 设置PropertyNameCaseInsensitive = true
-
JSON过大导致内存不足:
- 使用Utf8JsonReader/Utf8JsonWriter进行流式处理
- 分块处理数据
-
特殊字符转义问题:
- 注意中文和非ASCII字符的处理
- 考虑使用Base64编码二进制数据
9. 扩展方案与未来趋势
9.1 源码生成器
.NET 6引入的源码生成器可进一步提升性能:
csharp复制[JsonSerializable(typeof(Product))]
public partial class MyJsonContext : JsonSerializerContext { }
9.2 协议缓冲区
对于严格要求schema的场景,可考虑Protocol Buffers:
csharp复制[ProtoContract]
public class Product {
[ProtoMember(1)]
public int Id { get; set; }
// ...
}
经过多年实践,我发现没有"最佳"的JSON序列化方案,只有最适合特定场景的选择。对于新项目,我建议从System.Text.Json开始,在遇到特定需求时再考虑其他方案。关键是要在项目早期建立统一的序列化规范,避免后期出现格式混乱的问题。
