C# JSON序列化方法:全面解析与实践指南


引言

JSON(JavaScript Object Notation)作为现代应用中最流行的数据交换格式,在C#开发中扮演着至关重要的角色。无论是Web API开发、配置文件处理还是跨平台数据交换,高效的JSON序列化与反序列化都是开发者必须掌握的核心技能。本文将全面介绍C#中各种JSON处理方法,从基础使用到高级技巧,帮助开发者选择最适合项目需求的JSON处理方案。

一、C# JSON处理基础

1.1 JSON序列化核心概念

  • 序列化(Serialization):将对象转换为JSON字符串
  • 反序列化(Deserialization):将JSON字符串转换回对象
  • 常见应用场景
  • Web API请求/响应处理
  • 应用程序配置存储
  • 跨进程/跨平台数据交换
  • 数据持久化

1.2 .NET中的JSON处理库

  • System.Text.Json:.NET Core 3.0+内置的高性能库(推荐)
  • Newtonsoft.Json:功能丰富的流行第三方库
  • 其他选择:Jil、Utf8Json等

二、System.Text.Json使用指南

2.1 基础序列化与反序列化

using System.Text.Json;

// 定义示例类
public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
    public DateTime BirthDate { get; set; }
}

// 序列化对象到JSON
Person person = new Person 
{ 
    Name = "张三", 
    Age = 30, 
    BirthDate = new DateTime(1990, 1, 1) 
};

string jsonString = JsonSerializer.Serialize(person);
// 结果: {"Name":"张三","Age":30,"BirthDate":"1990-01-01T00:00:00"}

// 反序列化JSON到对象
Person deserializedPerson = JsonSerializer.Deserialize<Person>(jsonString);

2.2 高级配置选项

// 配置序列化选项
var options = new JsonSerializerOptions
{
    WriteIndented = true,               // 美化输出(缩进)
    PropertyNamingPolicy = JsonNamingPolicy.CamelCase, // 属性名驼峰式命名
    IgnoreNullValues = true,            // 忽略null值
    Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping, // 宽松的字符编码
    Converters = { new JsonStringEnumConverter() } // 枚举转换为字符串
};

string formattedJson = JsonSerializer.Serialize(person, options);
/*
输出:
{
  "name": "张三",
  "age": 30,
  "birthDate": "1990-01-01T00:00:00"
}
*/

2.3 处理复杂类型和自定义转换

// 自定义转换器示例
public class DateTimeConverter : JsonConverter<DateTime>
{
    private const string Format = "yyyy-MM-dd";

    public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        return DateTime.ParseExact(reader.GetString(), Format, CultureInfo.InvariantCulture);
    }

    public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
    {
        writer.WriteStringValue(value.ToString(Format, CultureInfo.InvariantCulture));
    }
}

// 使用自定义转换器
var options = new JsonSerializerOptions
{
    Converters = { new DateTimeConverter() }
};

string json = JsonSerializer.Serialize(person, options);
// {"Name":"张三","Age":30,"BirthDate":"1990-01-01"}

三、Newtonsoft.Json使用指南

3.1 基础使用方法

using Newtonsoft.Json;

// 序列化
string json = JsonConvert.SerializeObject(person);
// 反序列化
Person obj = JsonConvert.DeserializeObject<Person>(json);

// 带格式化的序列化
string prettyJson = JsonConvert.SerializeObject(person, Formatting.Indented);

3.2 高级配置选项

var settings = new JsonSerializerSettings
{
    Formatting = Formatting.Indented,
    NullValueHandling = NullValueHandling.Ignore,
    ContractResolver = new CamelCasePropertyNamesContractResolver(),
    DateFormatString = "yyyy-MM-dd",
    Converters = new List<JsonConverter> { new StringEnumConverter() }
};

string json = JsonConvert.SerializeObject(person, settings);

3.3 处理特殊场景

// 忽略属性
public class Product
{
    public string Name { get; set; }

    [JsonIgnore]
    public decimal Price { get; set; }
}

// 自定义属性名称
public class User
{
    [JsonProperty("user_name")]
    public string Name { get; set; }
}

// 处理循环引用
settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;

四、性能优化技巧

4.1 源生成器(Source Generator)

// 使用System.Text.Json源生成器
[JsonSerializable(typeof(Person))]
public partial class PersonJsonContext : JsonSerializerContext {}

// 使用生成的序列化代码
var json = JsonSerializer.Serialize(person, PersonJsonContext.Default.Person);
var obj = JsonSerializer.Deserialize(json, PersonJsonContext.Default.Person);

4.2 使用Utf8JsonReader和Utf8JsonWriter

// 高性能读取
var reader = new Utf8JsonReader(jsonBytes);
while (reader.Read())
{
    if (reader.TokenType == JsonTokenType.PropertyName)
    {
        var propertyName = reader.GetString();
        reader.Read();
        // 处理属性值...
    }
}

// 高性能写入
var buffer = new ArrayBufferWriter<byte>();
var writer = new Utf8JsonWriter(buffer);
writer.WriteStartObject();
writer.WriteString("name", "张三");
writer.WriteNumber("age", 30);
writer.WriteEndObject();
writer.Flush();

4.3 缓存与复用

// 缓存JsonSerializerOptions
private static readonly JsonSerializerOptions _options = new JsonSerializerOptions
{
    PropertyNamingPolicy = JsonNamingPolicy.CamelCase
};

// 复用配置
string json = JsonSerializer.Serialize(data, _options);

五、常见问题解决方案

5.1 处理多态类型

// System.Text.Json方法
[JsonDerivedType(typeof(Student), "student")]
[JsonDerivedType(typeof(Teacher), "teacher")]
public class Person { /*...*/ }

public class Student : Person { /*...*/ }
public class Teacher : Person { /*...*/ }

// Newtonsoft.Json方法
settings.TypeNameHandling = TypeNameHandling.Auto;

5.2 处理日期时间格式

// System.Text.Json
options.Converters.Add(new JsonDateTimeConverter("yyyy-MM-dd HH:mm:ss"));

// Newtonsoft.Json
settings.DateFormatString = "yyyy-MM-dd HH:mm:ss";

5.3 处理大数字精度问题

// 处理long类型在JavaScript中的精度问题
public class LongToStringConverter : JsonConverter<long>
{
    public override long ReadJson(JsonReader reader, Type objectType, long existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        return long.Parse(reader.Value.ToString());
    }

    public override void WriteJson(JsonWriter writer, long value, JsonSerializer serializer)
    {
        writer.WriteValue(value.ToString());
    }
}

六、库比较与选择建议

特性System.Text.JsonNewtonsoft.Json
性能更高中等
内存使用更低较高
功能丰富度基础非常丰富
依赖关系.NET内置需要NuGet包
自定义控制有限非常灵活
源生成支持支持不支持

选择建议

  1. 新项目:优先使用System.Text.Json,特别是性能敏感型应用
  2. 需要高级功能:考虑Newtonsoft.Json
  3. 迁移现有项目:逐步从Newtonsoft.Json迁移到System.Text.Json

七、实际应用示例

7.1 Web API中的JSON处理

// ASP.NET Core中配置JSON选项
services.AddControllers()
    .AddJsonOptions(options =>
    {
        options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
        options.JsonSerializerOptions.IgnoreNullValues = true;
        options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
    });

7.2 配置文件处理

// 读取JSON配置文件
var configJson = File.ReadAllText("appsettings.json");
var config = JsonSerializer.Deserialize<AppConfig>(configJson);

// 写入配置更新
var updatedJson = JsonSerializer.Serialize(config, new JsonSerializerOptions { WriteIndented = true });
File.WriteAllText("appsettings.json", updatedJson);

7.3 高性能数据处理管道

public async Task ProcessLargeJsonFileAsync(string filePath)
{
    await using var fileStream = File.OpenRead(filePath);
    var persons = JsonSerializer.DeserializeAsyncEnumerable<Person>(fileStream);

    await foreach (var person in persons)
    {
        // 流式处理每个对象,避免全部加载到内存
        ProcessPerson(person);
    }
}

结论

C#中的JSON序列化方法多种多样,开发者应根据项目需求选择最合适的方案:

  1. 对于性能优先的新项目:采用System.Text.Json并利用其源生成功能
  2. 需要丰富功能的复杂场景:考虑Newtonsoft.Json
  3. 处理超大JSON文件:使用流式API避免内存问题
  4. Web API开发:合理配置全局序列化选项

无论选择哪种方法,都应遵循以下最佳实践:

  • 明确处理日期、枚举等特殊类型的策略
  • 考虑国际化需求(如字符编码、日期格式)
  • 在性能敏感场景进行基准测试
  • 保持一致的命名策略和格式标准

通过掌握这些JSON处理技术,C#开发者能够高效地实现各种数据交换需求,构建更加健壮和高效的应用程序。


发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注