C# 序列化与反序列化详解:System.Text.Json、Newtonsoft.Json、XmlSerializer 用法、特性选项与安全实践

发布时间:2026/9/28 18:27:03
C# 序列化与反序列化详解:System.Text.Json、Newtonsoft.Json、XmlSerializer 用法、特性选项与安全实践 C# 序列化与反序列化详解System.Text.Json、Newtonsoft.Json、XmlSerializer 用法、特性选项与安全实践什么是序列化序列化就是把内存中的对象转换成可以存储或传输的格式如 JSON、XML、二进制反序列化则是把这些数据还原成内存对象。可以通俗理解为序列化是打包反序列化是拆包。无论是把数据存到文件/数据库、调用 Web API还是做微服务通信本质上都离不开序列化。本文从为什么需要序列化讲起系统梳理 C# 中各种序列化方式、常用特性与选项、安全与最佳实践适合初学者入门也可作为开发查阅手册。目录为什么需要序列化序列化基本语法核心机制特性与选项安全与最佳实践小结1. 为什么需要序列化序列化将对象转换为可存储或传输的格式如 JSON、XML、二进制。反序列化将存储或传输的格式还原为内存对象。痛点说明后果对象易失内存对象随进程结束而销毁无法持久化到磁盘、数据库或缓存无法直接传输对象引用不能跨进程、跨机器传递分布式通信、Web API 难以实现手动读写繁琐逐个字段拼装与解析易出错字段变更后容易不同步跨语言互操作差不同语言对象模型不一致系统集成成本高格式难统一序列化的解决方案将对象状态转换为标准格式在需要时再反序列化恢复。最常用 JSONSystem.Text.Json、Newtonsoft.Json也支持 XML、二进制、Protobuf 等格式。下图展示了序列化与反序列化的完整数据流转过程内存对象经序列化为 JSON/XML可用于持久化存储或网络传输需要时再反序列化还原为对象。【插图序列化与反序列化数据流转图】发布时在此插入图片序列化与反序列化数据流转图.png2. 序列化基本语法2.1 常用序列化方式方式命名空间/包格式特点建议System.Text.JsonSystem.Text.JsonJSON.NET 内置高性能支持源生成/AOT默认首选Newtonsoft.JsonNewtonsoft.JsonNuGetJSON功能丰富兼容性强配置灵活老项目或需要高级特性时使用XmlSerializerSystem.Xml.SerializationXML内置要求公共无参构造序列化公共成员传统 XML 接口DataContractSerializerSystem.Runtime.SerializationXML支持[DataContract]选择加入WCF 常用契约式 XMLBinaryFormatterSystem.Runtime.Serialization.Formatters.Binary二进制已弃用不安全禁止用于不可信数据Protobufprotobuf-net/Google.Protobuf二进制高性能、跨语言、体积小微服务、高性能通信2.2 模型设计规范规范说明使用公共属性System.Text.Json默认序列化公共属性不序列化公共字段除非IncludeFields true提供构造函数反序列化可用无参构造或带参构造 [JsonConstructor]避免循环引用使用[JsonIgnore]或ReferenceHandler使用 DTO不要直接序列化 EF 实体或领域模型避免暴露过度和循环引用初始化集合/字符串避免反序列化后出现null导致空引用版本兼容新增成员尽量可空或带默认值反序列化默认忽略未知成员2.3 使用示例最基础的对象 → JSON → 对象usingSystem.Text.Json;publicclassUser{publicintId{get;set;}publicstringName{get;set;}string.Empty;publicDateTimeCreatedAt{get;set;}}varusernewUser{Id1,NameAlice,CreatedAtDateTime.UtcNow};// 序列化对象 → JSON 字符串stringjsonJsonSerializer.Serialize(user,newJsonSerializerOptions{WriteIndentedtrue});Console.WriteLine(json);// 反序列化JSON 字符串 → 对象User?copyJsonSerializer.DeserializeUser(json);Console.WriteLine(copy?.Name);// Alice序列化后得到的 JSON 大致如下控制台默认保持属性原名日期为 ISO 8601 格式{Id:1,Name:Alice,CreatedAt:2026-09-27T08:30:00.0000000Z}带常用选项的写法usingSystem.Text.Json;usingSystem.Text.Json.Serialization;varoptionsnewJsonSerializerOptions{WriteIndentedtrue,// 缩进输出便于阅读PropertyNamingPolicyJsonNamingPolicy.CamelCase,// 属性名转小驼峰DefaultIgnoreConditionJsonIgnoreCondition.WhenWritingNull// null 值不输出};stringjsonJsonSerializer.Serialize(user,options);User?copyJsonSerializer.DeserializeUser(json,options);Newtonsoft.Json 的写法// 需先安装 NuGet 包Newtonsoft.JsonusingNewtonsoft.Json;stringjsonJsonConvert.SerializeObject(user,Formatting.Indented);User?copyJsonConvert.DeserializeObjectUser(json);XmlSerializer 的写法usingSystem.Xml.Serialization;varserializernewXmlSerializer(typeof(User));usingvarwriternewStringWriter();serializer.Serialize(writer,user);// 对象 → XMLstringxmlwriter.ToString();usingvarreadernewStringReader(xml);User?copy(User?)serializer.Deserialize(reader);// XML → 对象3. 核心机制特性与选项Attributes Options序列化框架通常通过特性控制单个成员的映射通过选项控制全局行为。没有配置时框架只按默认规则处理公共属性。3.1 常用特性总览特性所属库作用示例[JsonPropertyName]System.Text.Json指定 JSON 属性名[JsonPropertyName(user_name)][JsonIgnore]System.Text.Json忽略某个属性[JsonIgnore] public decimal Cost { get; set; }[JsonInclude]System.Text.Json包含非公共访问器[JsonInclude] public string Name { get; private set; }[JsonConverter]System.Text.Json指定自定义转换器[JsonConverter(typeof(JsonStringEnumConverter))][JsonConstructor]System.Text.Json指定反序列化构造函数[JsonConstructor] public User(int id) { }[JsonExtensionData]System.Text.Json捕获未知 JSON 属性public Dictionarystring, JsonElement? Extra { get; set; }[JsonPolymorphic]/[JsonDerivedType]System.Text.Json多态序列化.NET 7[JsonDerivedType(typeof(Dog), dog)][JsonProperty]Newtonsoft.Json指定名称、顺序、是否必需[JsonProperty(user_name)][DataContract]/[DataMember]System.Runtime.Serialization选择加入控制名称/顺序[DataMember(Name name, Order 1)][XmlElement]/[XmlAttribute]/[XmlIgnore]System.Xml.Serialization控制 XML 映射[XmlAttribute(id)][Serializable]System标记可二进制序列化旧不推荐用于BinaryFormatter[ProtoContract]/[ProtoMember]protobuf-netProtobuf 契约[ProtoMember(1)]3.2 常用选项总览选项作用常用值WriteIndented输出缩进 JSONtruePropertyNamingPolicy属性命名策略JsonNamingPolicy.CamelCasePropertyNameCaseInsensitive反序列化大小写不敏感trueDefaultIgnoreCondition默认忽略条件JsonIgnoreCondition.WhenWritingNullReferenceHandler循环引用处理ReferenceHandler.IgnoreCyclesConverters自定义转换器集合new JsonStringEnumConverter()Encoder字符编码策略JavaScriptEncoder.UnsafeRelaxedJsonEscapingNumberHandling数字读取策略JsonNumberHandling.AllowReadingFromStringIncludeFields包含公共字段trueTypeInfoResolver类型元数据解析源生成AppJsonContext.Default3.3 实战代码示例usingSystem.Text.Json;usingSystem.Text.Json.Serialization;publicclassOrder{[JsonPropertyName(order_id)]publicintId{get;set;}[JsonIgnore]publicdecimalInternalCost{get;set;}// 该属性不会被序列化publicstring?CustomerName{get;set;}[JsonConverter(typeof(JsonStringEnumConverter))]// 枚举输出为字符串publicOrderStatusStatus{get;set;}}publicenumOrderStatus{Pending,Paid,Shipped}varoptionsnewJsonSerializerOptions{WriteIndentedtrue,PropertyNamingPolicyJsonNamingPolicy.CamelCase,DefaultIgnoreConditionJsonIgnoreCondition.WhenWritingNull,PropertyNameCaseInsensitivetrue};varordernewOrder{Id1001,InternalCost30,CustomerName张三,StatusOrderStatus.Paid};stringjsonJsonSerializer.Serialize(order,options);Console.WriteLine(json);Order?backJsonSerializer.DeserializeOrder(json,options);输出示例{order_id:1001,customerName:张三,status:Paid}多态序列化示例.NET 7usingSystem.Text.Json.Serialization;[JsonPolymorphic(TypeDiscriminatorPropertyName$type)][JsonDerivedType(typeof(Dog),dog)][JsonDerivedType(typeof(Cat),cat)]publicabstractclassAnimal{publicstringName{get;set;}string.Empty;}publicclassDog:Animal{publicboolCanBark{get;set;}}publicclassCat:Animal{publicboolCanMeow{get;set;}}4. 安全与最佳实践实践说明默认选 System.Text.Json内置、高性能、支持源生成和 AOT禁用 BinaryFormatter不安全反序列化不可信数据可能导致远程代码执行.NET 5 已弃用.NET 9 移除不反序列化不可信类型避免类型混淆和恶意构造对象使用 DTO控制暴露字段隔离领域模型和数据库实体处理循环引用使用[JsonIgnore]或ReferenceHandler.IgnoreCycles/Preserve日期时间用 UTC使用 ISO 8601避免时区歧义枚举用字符串兼容性更好避免数值变化导致含义错乱敏感字段排除使用[JsonIgnore]或 DTO 不包含敏感信息大对象流式处理使用SerializeAsync/DeserializeAsync避免大字符串占内存版本兼容新增成员可空或带默认值反序列化默认忽略未知成员性能/AOT使用JsonSerializerContext源生成源生成示例提升启动性能、支持 AOTusingSystem.Text.Json;usingSystem.Text.Json.Serialization;[JsonSerializable(typeof(Order))]internalpartialclassAppJsonContext:JsonSerializerContext{}stringjsonJsonSerializer.Serialize(order,AppJsonContext.Default.Order);Order?backJsonSerializer.Deserialize(json,AppJsonContext.Default.Order);异步流式处理读写大文件避免一次性占用内存awaitusingvarstreamFile.Create(order.json);awaitJsonSerializer.SerializeAsync(stream,order,options);stream.Position0;Order?backawaitJsonSerializer.DeserializeAsyncOrder(stream,options);5. 小结序列化是对象 → 可存储/传输格式反序列化是其逆过程是持久化和网络通信的基础C# 中默认优先使用内置的System.Text.Json老项目或需要高级特性可用Newtonsoft.JsonXML 场景用XmlSerializer高性能跨语言可用 Protobuf用特性如[JsonPropertyName]、[JsonIgnore]、[JsonConverter]控制单个成员用JsonSerializerOptions控制命名、缩进、忽略、循环引用等全局行为安全上禁用 BinaryFormatter、不反序列化不可信数据、用 DTO 控制暴露字段大文件用异步流式、追求性能/AOT 用源生成。掌握定义模型 → 配置选项/特性 → 序列化与反序列化这套流程后日常的接口对接、配置存取、数据缓存都能轻松应对。建议对照本文代码亲手跑一遍观察不同选项下 JSON 的变化。