DotNetGuide序列化反序列化完全指南:从基础到高级实战
前言:为什么序列化反序列化如此重要?
在日常开发中,你是否遇到过这样的场景:
- 需要将对象数据持久化到文件或数据库中
- 不同系统间需要通过网络传输复杂的数据结构
- 需要缓存对象状态以便快速恢复
- API接口需要接收和返回结构化的数据
这些都是序列化(Serialization)和反序列化(Deserialization)技术的典型应用场景。作为.NET开发者,掌握序列化技术不仅能提升开发效率,更是构建高性能、可扩展应用的关键技能。
什么是序列化和反序列化?
基本概念
序列化(Serialization):将对象的状态信息转换为可以存储或传输的形式的过程 反序列化(Deserialization):将序列化后的数据重新转换为对象的过程
核心价值
- 数据持久化:将对象状态保存到文件或数据库
- 远程通信:在网络间传输对象数据
- 深度复制:通过序列化实现对象的深拷贝
- 缓存机制:将复杂对象缓存后快速恢复
.NET中的序列化技术体系
.NET提供了多种序列化方案,每种都有其适用场景:
技术选型对比表
| 技术方案 | 格式 | 性能 | 可读性 | 跨平台 | 适用场景 |
|---|---|---|---|---|---|
| System.Text.Json | JSON | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ✅ | Web API、配置文件 |
| Newtonsoft.Json | JSON | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ✅ | 复杂场景、遗留系统 |
| XmlSerializer | XML | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ✅ | SOAP、企业集成 |
| DataContractSerializer | XML | ⭐⭐⭐⭐ | ⭐⭐ | ✅ | WCF服务 |
| BinaryFormatter | 二进制 | ⭐⭐⭐⭐⭐ | ⭐ | ❌ | .NET内部通信 |
⚠️ 注意:BinaryFormatter由于安全漏洞,.NET 5+中已标记为过时,不建议在新项目中使用
System.Text.Json:现代.NET的首选
基础用法
using System.Text.Json;
// 定义数据模型
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public DateTime BirthDate { get; set; }
public List<string> Hobbies { get; set; }
}
// 序列化
var person = new Person
{
Name = "张三",
Age = 30,
BirthDate = new DateTime(1993, 5, 15),
Hobbies = new List<string> { "阅读", "编程", "旅行" }
};
string jsonString = JsonSerializer.Serialize(person, new JsonSerializerOptions
{
WriteIndented = true, // 格式化输出
PropertyNamingPolicy = JsonNamingPolicy.CamelCase // 驼峰命名
});
// 输出结果:
// {
// "name": "张三",
// "age": 30,
// "birthDate": "1993-05-15T00:00:00",
// "hobbies": ["阅读", "编程", "旅行"]
// }
// 反序列化
Person deserializedPerson = JsonSerializer.Deserialize<Person>(jsonString);
高级配置选项
var options = new JsonSerializerOptions
{
// 命名策略
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
// 忽略null值
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
// 允许注释
ReadCommentHandling = JsonCommentHandling.Skip,
// 允许尾随逗号
AllowTrailingCommas = true,
// 最大深度限制
MaxDepth = 64,
// 不转义字符
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
};
// 自定义转换器
options.Converters.Add(new DateTimeConverterUsingDateTimeParse());
处理复杂场景
// 多态序列化
[JsonDerivedType(typeof(Employee), typeDiscriminator: "employee")]
[JsonDerivedType(typeof(Manager), typeDiscriminator: "manager")]
public class Person
{
public string Name { get; set; }
}
public class Employee : Person
{
public string Department { get; set; }
}
public class Manager : Person
{
public int TeamSize { get; set; }
}
// 循环引用处理
options.ReferenceHandler = ReferenceHandler.Preserve;
Newtonsoft.Json:功能丰富的经典选择
虽然System.Text.Json是官方推荐,但Newtonsoft.Json在某些场景下仍有优势:
using Newtonsoft.Json;
// 复杂序列化配置
var settings = new JsonSerializerSettings
{
Formatting = Formatting.Indented,
NullValueHandling = NullValueHandling.Ignore,
DefaultValueHandling = DefaultValueHandling.Ignore,
ContractResolver = new CamelCasePropertyNamesContractResolver(),
Converters = new List<JsonConverter> { new StringEnumConverter() }
};
// 序列化
string json = JsonConvert.SerializeObject(person, settings);
// 反序列化
var result = JsonConvert.DeserializeObject<Person>(json, settings);
// 动态对象处理
dynamic dynamicObj = JsonConvert.DeserializeObject(json);
Console.WriteLine(dynamicObj.name);
XML序列化:企业级集成方案
XmlSerializer基础用法
using System.Xml.Serialization;
[XmlRoot("Person")]
public class Person
{
[XmlElement("FullName")]
public string Name { get; set; }
[XmlAttribute("Age")]
public int Age { get; set; }
[XmlIgnore]
public string Secret { get; set; }
}
// 序列化
var serializer = new XmlSerializer(typeof(Person));
using var writer = new StringWriter();
serializer.Serialize(writer, person);
string xml = writer.ToString();
// 反序列化
using var reader = new StringReader(xml);
var deserialized = (Person)serializer.Deserialize(reader);
DataContractSerializer
using System.Runtime.Serialization;
[DataContract]
public class Person
{
[DataMember(Name = "name", Order = 1)]
public string Name { get; set; }
[DataMember(Name = "age", Order = 2)]
public int Age { get; set; }
[IgnoreDataMember]
public string InternalId { get; set; }
}
// 序列化
var serializer = new DataContractSerializer(typeof(Person));
using var stream = new MemoryStream();
serializer.WriteObject(stream, person);
string xml = Encoding.UTF8.GetString(stream.ToArray());
性能优化技巧
1. 源生成器(Source Generation)
[JsonSerializable(typeof(Person))]
[JsonSerializable(typeof(List<Person>))]
public partial class MyJsonContext : JsonSerializerContext
{
}
// 使用源生成器进行序列化
string json = JsonSerializer.Serialize(person, MyJsonContext.Default.Person);
// 反序列化
Person p = JsonSerializer.Deserialize(json, MyJsonContext.Default.Person);
2. 池化技术减少内存分配
// 重用JsonSerializerOptions
private static readonly JsonSerializerOptions Options = new()
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
};
// 使用ArrayPool减少内存分配
byte[] buffer = ArrayPool<byte>.Shared.Rent(1024);
try
{
int bytesWritten = JsonSerializer.SerializeToUtf8Bytes(person, buffer, Options);
// 处理序列化结果
}
finally
{
ArrayPool<byte>.Shared.Return(buffer);
}
3. 异步序列化
// 异步序列化到Stream
await using var stream = new MemoryStream();
await JsonSerializer.SerializeAsync(stream, person, Options);
// 异步反序列化
stream.Position = 0;
Person result = await JsonSerializer.DeserializeAsync<Person>(stream, Options);
实战案例:构建高性能API序列化层
场景描述
构建一个电商平台的商品API,需要处理大量商品数据的序列化,要求:
- 高性能:支持1000+ QPS
- 低内存:减少GC压力
- 灵活性:支持多种输出格式
解决方案
// 定义统一的响应模型
public class ApiResponse<T>
{
public bool Success { get; set; }
public T Data { get; set; }
public string Message { get; set; }
}
// 序列化服务
public interface ISerializerService
{
string Serialize<T>(T obj);
T Deserialize<T>(string json);
byte[] SerializeToBytes<T>(T obj);
T DeserializeFromBytes<T>(byte[] data);
}
// System.Text.Json实现
public class SystemTextJsonSerializer : ISerializerService
{
private readonly JsonSerializerOptions _options;
public SystemTextJsonSerializer()
{
_options = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
WriteIndented = false
};
_options.Converters.Add(new JsonStringEnumConverter());
}
public string Serialize<T>(T obj) =>
JsonSerializer.Serialize(obj, _options);
public T Deserialize<T>(string json) =>
JsonSerializer.Deserialize<T>(json, _options);
public byte[] SerializeToBytes<T>(T obj) =>
JsonSerializer.SerializeToUtf8Bytes(obj, _options);
public T DeserializeFromBytes<T>(byte[] data) =>
JsonSerializer.Deserialize<T>(data, _options);
}
// 在ASP.NET Core中配置
builder.Services.AddSingleton<ISerializerService, SystemTextJsonSerializer>();
// 控制器中使用
[ApiController]
[Route("api/products")]
public class ProductsController : ControllerBase
{
private readonly ISerializerService _serializer;
public ProductsController(ISerializerService serializer)
{
_serializer = serializer;
}
[HttpGet("{id}")]
public IActionResult GetProduct(int id)
{
var product = _productService.GetProduct(id);
var response = new ApiResponse<Product>
{
Success = true,
Data = product
};
return Content(_serializer.Serialize(response), "application/json");
}
}
常见问题与解决方案
1. 循环引用问题
// System.Text.Json解决方案
options.ReferenceHandler = ReferenceHandler.Preserve;
// Newtonsoft.Json解决方案
settings.PreserveReferencesHandling = PreserveReferencesHandling.All;
2. 日期时间处理
// 统一日期格式
options.Converters.Add(new DateTimeConverter("yyyy-MM-dd HH:mm:ss"));
// 时区处理
public class DateTimeConverter : JsonConverter<DateTime>
{
public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
return DateTime.Parse(reader.GetString()).ToUniversalTime();
}
public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
{
writer.WriteStringValue(value.ToUniversalTime().ToString("O"));
}
}
3. 版本兼容性
// 使用Optional特性处理字段增减
public class Person
{
[JsonExtensionData]
public Dictionary<string, object> ExtensionData { get; set; }
}
性能基准测试
使用BenchmarkDotNet进行性能对比:
[MemoryDiagnoser]
public class SerializationBenchmark
{
private readonly Person _testPerson;
private readonly JsonSerializerOptions _stjOptions;
private readonly JsonSerializerSettings _nsSettings;
public SerializationBenchmark()
{
_testPerson = CreateTestData();
_stjOptions = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
_nsSettings = new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() };
}
[Benchmark]
public string SystemTextJson_Serialize() =>
JsonSerializer.Serialize(_testPerson, _stjOptions);
[Benchmark]
public string NewtonsoftJson_Serialize() =>
JsonConvert.SerializeObject(_testPerson, _nsSettings);
// 反序列化基准测试...
}
// 典型结果:
// | Method | Mean | Allocated |
// |-------------------------|-----------|-----------|
// | SystemTextJson_Serialize| 1.25 μs | 2.5 KB |
// | NewtonsoftJson_Serialize| 3.45 μs | 5.8 KB |
最佳实践总结
- 首选System.Text.Json:新项目优先选择,性能更优
- 合理配置选项:根据场景调整命名策略、忽略规则等
- 使用源生成器:AOT编译和性能敏感场景必备
- 注意内存管理:重用配置对象,使用池化技术
- 处理边界情况:循环引用、日期时间、版本兼容
- 异步操作:大数据量时使用异步序列化
- 安全考虑:避免反序列化不可信数据
扩展学习路径
通过本指南,你应该已经掌握了.NET中序列化反序列化的核心概念、技术选型和最佳实践。在实际项目中,根据具体需求选择合适的方案,并持续关注性能优化和安全考虑,将帮助你构建更加健壮和高效的应用程序。
💡 提示:记得在实际项目中进行性能测试和压力测试,确保选择的方案能够满足你的具体需求。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



