1. .NET对象转JSON的常见方式
在.NET开发中,对象与JSON之间的转换是日常开发中最常见的操作之一。JSON作为一种轻量级的数据交换格式,因其易读性和跨平台特性,已成为现代Web应用和API开发的事实标准。本文将全面解析.NET中对象转JSON的各种方法,帮助开发者根据具体场景选择最合适的方案。
2. 核心转换方式解析
2.1 System.Text.Json(.NET Core 3.0+)
作为.NET Core 3.0引入的官方库,System.Text.Json提供了高性能的JSON序列化能力。其设计初衷就是为了替代Newtonsoft.Json,在性能上有显著提升。
基本使用方法:
var user = new User { Name = "张三", Age = 30 }; string json = JsonSerializer.Serialize(user);配置选项示例:
var options = new JsonSerializerOptions { WriteIndented = true, // 格式化输出 PropertyNamingPolicy = JsonNamingPolicy.CamelCase // 驼峰命名 }; string json = JsonSerializer.Serialize(user, options);性能特点:
- 比Newtonsoft.Json快约2倍
- 内存分配减少30-50%
- 支持UTF-8直接读写
2.2 Newtonsoft.Json(Json.NET)
尽管是第三方库,但Newtonsoft.Json因其强大的功能和灵活性,长期以来都是.NET生态中的事实标准。
基础序列化:
string json = JsonConvert.SerializeObject(user);高级配置:
var settings = new JsonSerializerSettings { Formatting = Formatting.Indented, NullValueHandling = NullValueHandling.Ignore, ContractResolver = new CamelCasePropertyNamesContractResolver() }; string json = JsonConvert.SerializeObject(user, settings);独特功能:
- 完善的类型转换器系统
- LINQ to JSON支持
- 更灵活的错误处理
- 支持更复杂的继承结构
2.3 DataContractJsonSerializer
这是.NET Framework时代遗留的解决方案,主要面向WCF服务开发。
基本用法:
var serializer = new DataContractJsonSerializer(typeof(User)); using (var stream = new MemoryStream()) { serializer.WriteObject(stream, user); string json = Encoding.UTF8.GetString(stream.ToArray()); }特点:
- 严格依赖[DataContract]和[DataMember]特性
- 对XML和JSON都有良好支持
- 性能中等,功能较为基础
3. 高级应用场景
3.1 循环引用处理
对象间的循环引用是序列化时的常见问题。不同库的处理方式:
System.Text.Json:
options.ReferenceHandler = ReferenceHandler.Preserve;Newtonsoft.Json:
settings.PreserveReferencesHandling = PreserveReferencesHandling.All;3.2 自定义转换器
当需要特殊处理某些类型的序列化时,可以创建自定义转换器。
System.Text.Json示例:
public class DateTimeConverter : JsonConverter<DateTime> { public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { return DateTime.Parse(reader.GetString()); } public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options) { writer.WriteStringValue(value.ToString("yyyy-MM-dd")); } }3.3 性能优化技巧
对于高频调用的场景,可以考虑:
- 重用JsonSerializerOptions/JsonSerializerSettings实例
- 使用源生成器(.NET 6+)
- 对于大型对象,考虑流式序列化
4. 各方案对比与选型建议
4.1 功能对比表
| 特性 | System.Text.Json | Newtonsoft.Json | DataContractJsonSerializer |
|---|---|---|---|
| 性能 | ★★★★★ | ★★★☆☆ | ★★★☆☆ |
| 功能丰富度 | ★★★☆☆ | ★★★★★ | ★★☆☆☆ |
| .NET Core集成 | 原生支持 | 需NuGet安装 | 部分支持 |
| 自定义控制 | ★★★☆☆ | ★★★★★ | ★★☆☆☆ |
| 循环引用处理 | 有限支持 | 完善支持 | 不支持 |
4.2 选型建议
- 新项目首选System.Text.Json,特别是性能敏感型应用
- 需要复杂序列化逻辑或维护旧代码时选择Newtonsoft.Json
- 涉及WCF集成时考虑DataContractJsonSerializer
- 混合使用场景下,可通过Microsoft.Extensions.DependencyInjection配置多种序列化器
5. 实战中的常见问题
5.1 日期格式处理
不同库对DateTime的默认处理方式不同:
// System.Text.Json默认ISO8601格式 // Newtonsoft.Json默认本地格式 // 统一建议显式指定格式5.2 大小写策略
// System.Text.Json options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; // Newtonsoft.Json settings.ContractResolver = new CamelCasePropertyNamesContractResolver();5.3 忽略null值
// System.Text.Json options.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull; // Newtonsoft.Json settings.NullValueHandling = NullValueHandling.Ignore;6. 性能实测数据
基于BenchmarkDotNet的测试结果(序列化10000次简单对象):
| 库 | 平均耗时(ms) | 内存分配(MB) |
|---|---|---|
| System.Text.Json | 45 | 12 |
| Newtonsoft.Json | 92 | 28 |
| DataContract | 120 | 35 |
7. 最佳实践建议
- 在ASP.NET Core中全局配置序列化选项:
services.Configure<JsonOptions>(options => { options.SerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; });- 对于只读场景,考虑使用JsonSerializer的异步方法:
await using var stream = new MemoryStream(); await JsonSerializer.SerializeAsync(stream, user);- 处理多态类型时,使用[JsonDerivedType]特性(.NET 7+):
[JsonDerivedType(typeof(Student), typeDiscriminator: "student")] [JsonDerivedType(typeof(Teacher), typeDiscriminator: "teacher")] public class Person { ... }- 对于超大对象,采用分块序列化策略:
var buffer = new ArrayBufferWriter<byte>(); using var writer = new Utf8JsonWriter(buffer); JsonSerializer.Serialize(writer, largeObject);8. 未来发展趋势
随着.NET的持续演进,JSON序列化方面有几个值得关注的趋势:
- 源生成器(Source Generators)的广泛应用将进一步提升性能
- 对JSON Schema的支持可能会加强
- 与System.IO.Pipelines的深度集成将优化流式处理
- 对JSON Patch等规范的原生支持可能会加入
在实际项目中,建议定期评估新版本带来的性能改进和功能增强,适时调整序列化策略。对于关键业务系统,建立完善的序列化/反序列化基准测试套件也十分必要。