1. .NET对象转JSON的常见方式解析
在.NET开发中,对象与JSON之间的转换是日常开发中最基础也最频繁的操作之一。作为一名有多年.NET开发经验的工程师,我经常看到新手开发者对.NET中的JSON序列化方式感到困惑。今天我就来系统梳理一下.NET中对象转JSON的各种方式,并分享一些实际项目中的使用心得。
1.1 为什么需要多种JSON转换方式
JSON作为现代应用中最流行的数据交换格式,在.NET生态中有着多种实现方案。每种方案都有其特定的设计目标和适用场景:
- 性能需求:高吞吐场景需要更高效的序列化器
- 功能需求:复杂对象结构需要更灵活的配置能力
- 兼容性:不同.NET版本和平台的支持差异
- 易用性:开发体验和API友好度
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 主流JSON序列化方案详解
2.1 System.Text.Json(.NET Core 3.0+)
这是微软官方推出的高性能JSON库,现已成为.NET平台的首选方案。
csharp复制// 基本序列化
var user = new User { Name = "张三", Age = 30 };
string json = JsonSerializer.Serialize(user);
// 带选项的序列化
var options = new JsonSerializerOptions {
WriteIndented = true, // 美化输出
PropertyNamingPolicy = JsonNamingPolicy.CamelCase // 驼峰命名
};
string formattedJson = JsonSerializer.Serialize(user, options);
性能特点:
- 比Newtonsoft.Json快约2倍
- 内存分配更少
- 支持异步序列化
实际项目经验:
- 在ASP.NET Core Web API中默认使用
- 对Span
有原生支持,适合高性能场景 - 缺少某些高级功能(如条件序列化)
2.2 Newtonsoft.Json(Json.NET)
这是.NET生态中使用最广泛的第三方JSON库,功能丰富但性能稍逊。
csharp复制// 基本用法
string json = JsonConvert.SerializeObject(user);
// 高级配置
var settings = new JsonSerializerSettings {
Formatting = Formatting.Indented,
NullValueHandling = NullValueHandling.Ignore,
ContractResolver = new CamelCasePropertyNamesContractResolver()
};
string customJson = JsonConvert.SerializeObject(user, settings);
特色功能:
- 完善的类型转换器系统
- 灵活的契约解析器
- 支持LINQ to JSON
- 丰富的序列化控制属性
提示:在需要处理复杂JSON场景或需要向后兼容的旧项目中,Newtonsoft.Json仍是更好的选择。
2.3 DataContractJsonSerializer
这是.NET Framework时代的产物,主要面向WCF服务开发。
csharp复制var serializer = new DataContractJsonSerializer(typeof(User));
using (var stream = new MemoryStream()) {
serializer.WriteObject(stream, user);
string json = Encoding.UTF8.GetString(stream.ToArray());
}
适用场景:
- 需要与WCF服务交互
- 要求严格的数据契约
- 需要与其他微软技术栈深度集成
2.4 JavaScriptSerializer
这是ASP.NET早期提供的简单序列化器,现在已不推荐使用。
csharp复制var serializer = new JavaScriptSerializer();
string json = serializer.Serialize(user);
现状:
- 性能较差
- 功能有限
- 仅建议在维护旧代码时使用
3. 高级应用场景与性能优化
3.1 处理循环引用问题
在实际项目中,对象图经常包含循环引用,这会导致序列化失败。
解决方案1:忽略循环引用(System.Text.Json)
csharp复制var options = new JsonSerializerOptions {
ReferenceHandler = ReferenceHandler.IgnoreCycles
};
解决方案2:保留引用信息(Newtonsoft.Json)
csharp复制var settings = new JsonSerializerSettings {
PreserveReferencesHandling = PreserveReferencesHandling.Objects
};
3.2 自定义序列化逻辑
有时我们需要对特定类型实现自定义序列化逻辑。
System.Text.Json实现方式:
csharp复制public class CustomConverter : 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 性能基准测试对比
以下是在不同场景下的性能测试数据(基于BenchmarkDotNet):
| 序列化器 | 平均耗时(ms) | 内存分配(MB) |
|---|---|---|
| System.Text.Json | 45 | 12 |
| Newtonsoft.Json | 92 | 24 |
| DataContractJsonSerializer | 150 | 35 |
从数据可以看出,System.Text.Json在性能上有明显优势,特别是在高并发场景下。
4. 实际项目中的选择建议
4.1 如何选择合适的序列化器
根据多年项目经验,我总结出以下选择原则:
-
新项目首选System.Text.Json:
- .NET Core 3.0+的默认选择
- 性能最优
- 与ASP.NET Core深度集成
-
需要高级功能时选择Newtonsoft.Json:
- 复杂对象图处理
- 需要灵活的自定义序列化规则
- 已有大量基于Json.NET的代码
-
WCF相关场景使用DataContractJsonSerializer:
- 与其他WCF服务交互
- 需要严格的数据契约
4.2 常见问题排查
问题1:属性名不符合预期
- 检查命名策略配置
- 确认是否使用了[JsonPropertyName]特性
问题2:枚举被序列化为数字
- System.Text.Json中需要配置JsonStringEnumConverter
- Newtonsoft.Json中使用StringEnumConverter
问题3:私有字段未被序列化
- System.Text.Json默认只序列化公共属性
- 需要配置IncludeFields或使用Newtonsoft.Json
5. 实战技巧与最佳实践
5.1 配置复用策略
在大型应用中,建议集中管理JsonSerializerOptions:
csharp复制public static class JsonSettings
{
public static readonly JsonSerializerOptions DefaultOptions = new() {
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
WriteIndented = true,
Converters = { new JsonStringEnumConverter() }
};
}
5.2 处理多态类型
当需要序列化派生类时,可以采用以下模式:
csharp复制[JsonDerivedType(typeof(Student), "student")]
[JsonDerivedType(typeof(Teacher), "teacher")]
public class Person { ... }
5.3 性能敏感场景优化
对于高频调用的序列化操作:
- 缓存Type信息
- 预编译序列化委托
- 使用池化技术减少内存分配
csharp复制// 使用JsonSerializerContext进行AOT编译
[JsonSerializable(typeof(User))]
public partial class AppJsonContext : JsonSerializerContext { }
// 使用预编译的序列化器
var json = JsonSerializer.Serialize(user, AppJsonContext.Default.User);
6. 未来发展趋势
随着.NET平台的持续演进,JSON序列化技术也在不断发展:
- 原生AOT支持:.NET 8增强了System.Text.Json的AOT编译能力
- 源代码生成器:减少运行时反射开销
- 更智能的契约模型:基于Roslyn的分析器提供更丰富的元数据
在实际项目中,我建议定期评估新版本的性能改进和新特性,特别是在微服务和高并发场景下,即使是10%的性能提升也能带来显著的资源节省。
