
1. .NET对象转JSON的常见场景与需求在.NET开发中对象与JSON之间的转换是日常开发中最频繁的操作之一。无论是Web API的请求响应、前端数据交互还是微服务间的通信JSON作为轻量级的数据交换格式都扮演着关键角色。根据我的项目经验一个中等规模的Web应用平均每天要进行上万次这样的转换操作。为什么这个操作如此重要首先JSON格式具有良好的可读性和跨平台特性几乎被所有现代编程语言支持。其次在前后端分离架构中JSON是前后端通信的事实标准。更重要的是合理的序列化配置直接影响API的性能和安全性。2. 基础序列化方式JsonSerializer2.1 System.Text.Json基础用法.NET Core 3.0开始引入的System.Text.Json是目前官方推荐的JSON处理库它相比之前的Newtonsoft.Json有更好的性能表现。基础用法非常简单using System.Text.Json; var user new User { Id 1, Name 张三 }; string json JsonSerializer.Serialize(user); // 输出: {Id:1,Name:张三} User deserializedUser JsonSerializer.DeserializeUser(json);这个基础版本已经能满足大多数简单场景但实际项目中我们通常需要更多控制2.2 常用配置选项通过JsonSerializerOptions可以定制序列化行为var options new JsonSerializerOptions { WriteIndented true, // 美化输出 PropertyNamingPolicy JsonNamingPolicy.CamelCase, // 驼峰命名 IgnoreNullValues true, // 忽略null值 Encoder JavaScriptEncoder.UnsafeRelaxedJsonEscaping // 宽松的字符编码 }; string json JsonSerializer.Serialize(user, options);重要提示JavaScriptEncoder.UnsafeRelaxedJsonEscaping会减少不必要的转义但可能带来XSS风险仅限在可信环境中使用。2.3 性能优化技巧重用JsonSerializerOptions实例每次创建新实例会导致策略缓存失效使用Source Generation.NET 6支持编译时代码生成[JsonSerializable(typeof(User))] public partial class UserContext : JsonSerializerContext {} // 使用生成的序列化器 string json JsonSerializer.Serialize(user, UserContext.Default.User);3. 高级序列化控制3.1 自定义属性名称通过[JsonPropertyName]特性可以指定属性在JSON中的名称public class User { [JsonPropertyName(user_id)] public int Id { get; set; } [JsonIgnore] // 完全忽略该属性 public string Password { get; set; } }3.2 处理循环引用当对象存在循环引用时默认会抛出异常。可以通过以下方式处理options.ReferenceHandler ReferenceHandler.Preserve; // 输出: {$id:1,Id:1,Manager:{$ref:1}}3.3 多态序列化处理继承体系时需要特别配置[JsonDerivedType(typeof(Student), typeDiscriminator: student)] [JsonDerivedType(typeof(Teacher), typeDiscriminator: teacher)] public class Person { ... } var people new ListPerson { new Student(), new Teacher() }; string json JsonSerializer.Serialize(people, options); // 输出包含类型鉴别器字段4. Newtonsoft.Json的对比使用4.1 基本差异虽然System.Text.Json是官方推荐但Newtonsoft.Json(Json.NET)仍广泛使用主要区别特性System.Text.JsonNewtonsoft.Json性能更高较低内存分配更少较多功能丰富度基础全面依赖注入支持内置需扩展4.2 典型使用场景Newtonsoft.Json在以下场景仍有优势需要复杂转换逻辑时处理动态JSON时需要更灵活的类型转换时// Newtonsoft.Json的动态处理 dynamic obj JObject.Parse(json); string name obj.Name; // 自定义转换器 public class DateTimeConverter : JsonConverterDateTime { public override DateTime ReadJson(...) { ... } public override void WriteJson(...) { ... } }5. 实战中的性能优化5.1 基准测试对比通过BenchmarkDotNet测试不同方案的性能方法均值(ns)分配内存System.Text.Json120192 BNewtonsoft.Json350512 BSource Generation85128 B5.2 内存池的使用对于高频场景使用ArrayBufferWriter减少GC压力var buffer new ArrayBufferWriterbyte(); using var writer new Utf8JsonWriter(buffer); JsonSerializer.Serialize(writer, user); // 从buffer.WrittenSpan获取结果5.3 异步序列化处理大对象时使用异步避免阻塞await using var stream new MemoryStream(); await JsonSerializer.SerializeAsync(stream, largeObject);6. 安全注意事项6.1 反序列化风险不安全的反序列化可能导致类型注入攻击敏感数据泄露服务拒绝防护措施var options new JsonSerializerOptions { TypeInfoResolver new DefaultJsonTypeInfoResolver { Modifiers { ValidateTypeInfo } } }; static void ValidateTypeInfo(JsonTypeInfo typeInfo) { if (typeInfo.Type typeof(FileInfo)) throw new NotSupportedException(危险类型禁止反序列化); }6.2 深度限制防止栈溢出攻击options.MaxDepth 32; // 默认647. 特殊场景处理7.1 日期时间格式统一日期格式的最佳实践options.Converters.Add(new DateTimeConverter(yyyy-MM-dd HH:mm:ss));7.2 枚举处理控制枚举的序列化方式options.Converters.Add(new JsonStringEnumConverter()); // 作为字符串7.3 字典键的处理自定义字典键的序列化options.DictionaryKeyPolicy JsonNamingPolicy.CamelCase;8. 调试与问题排查8.1 常见异常处理JsonException: 格式错误时抛出NotSupportedException: 不支持的类型ArgumentException: 无效参数8.2 诊断工具使用JsonDocument分析JSON结构using JsonDocument doc JsonDocument.Parse(json); foreach (JsonProperty prop in doc.RootElement.EnumerateObject()) { Console.WriteLine(${prop.Name}: {prop.Value}); }8.3 性能分析使用DiagnosticSource监听序列化事件var listener new JsonEventListener(); using IDisposable subscription DiagnosticListener.AllListeners.Subscribe(listener); class JsonEventListener : IObserverDiagnosticListener { public void OnNext(DiagnosticListener listener) { if (listener.Name System.Text.Json) { listener.Subscribe(new JsonEventCollector()); } } // 其他接口实现... }在实际项目中我遇到过因为不当的序列化配置导致API性能下降50%的情况。经过分析发现是频繁创建JsonSerializerOptions实例导致的。通过将其缓存为静态实例性能立即恢复到正常水平。另一个常见问题是循环引用导致的栈溢出这在对象关系复杂的领域模型中尤其常见需要特别注意处理。