DotNetGuide序列化反序列化完全指南:从基础到高级实战

DotNetGuide序列化反序列化完全指南:从基础到高级实战

【免费下载链接】DotNetGuide 🌈【C#/.NET/.NET Core学习、工作、面试指南】记录、收集和总结C#/.NET/.NET Core基础知识、学习路线、开发实战、编程技巧练习、学习视频、文章、书籍、项目框架、社区组织、开发必备工具、技术前沿周刊、常见面试题、面试须知、简历模板、人才招聘、以及自己在学习和工作中的一些微薄见解。希望能和大家一起学习,共同进步。如果本知识库能为您提供帮助,别忘了给予支持哦(关注、点赞、分享)💖。 【免费下载链接】DotNetGuide 项目地址: https://gitcode.com/DotNetGuide/DotNetGuide

前言:为什么序列化反序列化如此重要?

在日常开发中,你是否遇到过这样的场景:

  • 需要将对象数据持久化到文件或数据库中
  • 不同系统间需要通过网络传输复杂的数据结构
  • 需要缓存对象状态以便快速恢复
  • API接口需要接收和返回结构化的数据

这些都是序列化(Serialization)和反序列化(Deserialization)技术的典型应用场景。作为.NET开发者,掌握序列化技术不仅能提升开发效率,更是构建高性能、可扩展应用的关键技能。

什么是序列化和反序列化?

基本概念

序列化(Serialization):将对象的状态信息转换为可以存储或传输的形式的过程 反序列化(Deserialization):将序列化后的数据重新转换为对象的过程

mermaid

核心价值

  1. 数据持久化:将对象状态保存到文件或数据库
  2. 远程通信:在网络间传输对象数据
  3. 深度复制:通过序列化实现对象的深拷贝
  4. 缓存机制:将复杂对象缓存后快速恢复

.NET中的序列化技术体系

.NET提供了多种序列化方案,每种都有其适用场景:

技术选型对比表

技术方案格式性能可读性跨平台适用场景
System.Text.JsonJSON⭐⭐⭐⭐⭐⭐⭐⭐⭐Web API、配置文件
Newtonsoft.JsonJSON⭐⭐⭐⭐⭐⭐⭐⭐⭐复杂场景、遗留系统
XmlSerializerXML⭐⭐⭐⭐⭐⭐⭐⭐SOAP、企业集成
DataContractSerializerXML⭐⭐⭐⭐⭐⭐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    |

最佳实践总结

  1. 首选System.Text.Json:新项目优先选择,性能更优
  2. 合理配置选项:根据场景调整命名策略、忽略规则等
  3. 使用源生成器:AOT编译和性能敏感场景必备
  4. 注意内存管理:重用配置对象,使用池化技术
  5. 处理边界情况:循环引用、日期时间、版本兼容
  6. 异步操作:大数据量时使用异步序列化
  7. 安全考虑:避免反序列化不可信数据

扩展学习路径

mermaid

通过本指南,你应该已经掌握了.NET中序列化反序列化的核心概念、技术选型和最佳实践。在实际项目中,根据具体需求选择合适的方案,并持续关注性能优化和安全考虑,将帮助你构建更加健壮和高效的应用程序。

💡 提示:记得在实际项目中进行性能测试和压力测试,确保选择的方案能够满足你的具体需求。

【免费下载链接】DotNetGuide 🌈【C#/.NET/.NET Core学习、工作、面试指南】记录、收集和总结C#/.NET/.NET Core基础知识、学习路线、开发实战、编程技巧练习、学习视频、文章、书籍、项目框架、社区组织、开发必备工具、技术前沿周刊、常见面试题、面试须知、简历模板、人才招聘、以及自己在学习和工作中的一些微薄见解。希望能和大家一起学习,共同进步。如果本知识库能为您提供帮助,别忘了给予支持哦(关注、点赞、分享)💖。 【免费下载链接】DotNetGuide 项目地址: https://gitcode.com/DotNetGuide/DotNetGuide

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值