引言
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.Json | Newtonsoft.Json |
---|---|---|
性能 | 更高 | 中等 |
内存使用 | 更低 | 较高 |
功能丰富度 | 基础 | 非常丰富 |
依赖关系 | .NET内置 | 需要NuGet包 |
自定义控制 | 有限 | 非常灵活 |
源生成支持 | 支持 | 不支持 |
选择建议:
- 新项目:优先使用System.Text.Json,特别是性能敏感型应用
- 需要高级功能:考虑Newtonsoft.Json
- 迁移现有项目:逐步从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序列化方法多种多样,开发者应根据项目需求选择最合适的方案:
- 对于性能优先的新项目:采用System.Text.Json并利用其源生成功能
- 需要丰富功能的复杂场景:考虑Newtonsoft.Json
- 处理超大JSON文件:使用流式API避免内存问题
- Web API开发:合理配置全局序列化选项
无论选择哪种方法,都应遵循以下最佳实践:
- 明确处理日期、枚举等特殊类型的策略
- 考虑国际化需求(如字符编码、日期格式)
- 在性能敏感场景进行基准测试
- 保持一致的命名策略和格式标准
通过掌握这些JSON处理技术,C#开发者能够高效地实现各种数据交换需求,构建更加健壮和高效的应用程序。