Json的序列化与反序列化(System.Text.Json)大家都会用,但是大家都会用得比较模糊,本文通过详细的讲解使大家清晰的讲握System.Text.Json的使用,因为...“清晰”是知识真正被学习和掌握的标志😊.
为什么一定是System.Text.Json😊 ?
.NET中有很多好的开源Json解析框架,如: Newtonsoft.Json,为什么一定要使用System.Text.Json?
因为:
- 微软的官方包,它在.NET Core 3.0及更高版本中提供了内置支持,微软官方代码都是使用System.Text.Json,了解它很重要!
- 性能表现优秀,官方讲的是:高性能和低内存分配!
- 多线程安全性;
术语解释:
序列化:把对象变成字符串,即:Object--> string
反序列化: 把字符串转成对象,即: string--> Object
涉及的命名空间 🚀🚀
- System.Text.Json: 最主要提供了序列化与反序列化的核心类:如JsonSerializer等;
- System.Text.Json.Serialization: 提供象[JsonPropertyName]等特性、JsonSerializerOptions的扩展的支持;
- System.Net.Http.Json: 给HttpClient类使用,在进行Http访问时将返回的内容进行反序列化,这个在使用HttpClient的时会提供极大的方便;
基本使用(序列化/反序列化) 🎉🎉
-
序列化
使用JsonSerializer.Serialize()或者重载的使用JsonSerializer.Serialize版本,System.Text.Json为也提供异步版本
using demo;
using System.Text.Json;
using System.Text.Json.Serialization;
var persion = new Person("John Doe", 30,true, new DateTime(1993, 5, 15));
var jsonString = JsonSerializer.Serialize(persion);
var jsonString2 = JsonSerializer.Serialize<Person>(persion);
Console.WriteLine(jsonString);
Console.WriteLine(jsonString2);
//output: {"Name":"John Doe","Age":30,"IsStudent":true,"Birthday":"1993-05-15T00:00:00"}
注意这里的输出: 默认情况下,JSON 输出会被缩小(将删除空格、缩进和换行符),如果在日志的场合,这个不好观察日志输出,下面论述中的JsonSerializerOptions类可以使输出更容易观测,详见下面的论述。
- 反序列化
使用JsonSerializer.Deserialize()或者重载的使用JsonSerializer.Deserialize版本,System.Text.Json为也提供异步版本供反序列化;
using demo;
using System.Text.Json;
using System.Text.Json.Serialization;
var jsonString = """
{"Date":"2025-06-23T01:11:58.4217508+08:00","TemperatureCelsius":25,"Summary":"Sunny","Wind":10}
""";
var jsonObject = JsonSerializer.Deserialize<WeatherForecast>(jsonString);
Console.WriteLine(jsonObject?.Date);
Console.WriteLine(jsonObject?.TemperatureCelsius);
Console.WriteLine(jsonObject?.Summary);
Console.WriteLine(jsonObject?.WindSpeed);
对序列化/反序列化行为的控制 🚀🚀
何谓"行为控制"?😂
例如:我们在进行前后端开发的时候,前端的对象的字段一般为驼峰命名,而我们在后端用C#写程序用的是Pascal命名法,所以我们需要转换属性名,这个就需要对序列化/反序列化行为进行控制;
例如:System.Text.Json默认只对公开的属性进行序列化/反序列化,而默认不会对字段进行序列化/反序列化,这个时候,我们也需要对序列化/反序列化的行为进行控制;
有两种对序列化/反序列化行为的控制方法:
- 使用特性[JsonPropertyName]、[JsonIgnore]、[JsonInclude]等
- 使用JsonSerializerOptions类
注1:使用特性与JsonSerializerOptions类都能对序列化/反序列化的行为进行控制,但是特性更多应用在单个类、单个字段,而JsonSerializerOptions类更多用于全局控制及实际很多特性无法完成的json实例化/反实例化控制,所以下面最主要介绍JsonSerializerOptions类
注2: 特性的权重更高,意味着如果同时设置了特性并同时也受JsonSerializerOptions的约束,那么特性的权重更高,会覆盖JsonSerializerOptions的设置
JsonSerializerOptions
- 自定义属性名
using demo;
using System.Text.Json;
using System.Text.Json.Serialization;
var weather = new WeatherForecast()
{
Date = DateTimeOffset.Now,
TemperatureCelsius = 25,
Summary = "Sunny",
WindSpeed = 10
};
var jsonoptions = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
};
var json = JsonSerializer.Serialize(weather, jsonoptions);
Console.WriteLine(json);
输出是:
{"date":"2025-06-23T02:04:44.6282091+08:00","temperatureCelsius":25,"summary":"Sunny","Wind":10}
所有字段名变成web的驼峰命名😊
内置可选的命名策略:(基本上够用,也可以自定义)
| 命名策略 | 说明 | 原始属性名称 | 经过转换的属性名称 |
|---|---|---|---|
| CamelCase | 第一个单词以小写字符开头。 连续单词以大写字符开头。 | TempCelsius | tempCelsius |
| KebabCaseLower* | 单词由连字符分隔。 所有字符均为小写。 | TempCelsius | temp-celsius |
| KebabCaseUpper* | 单词由连字符分隔。 所有字符均为大写。 | TempCelsius | TEMP-CELSIUS |
| SnakeCaseLower* | 单词用下划线分隔。 所有字符均为小写。 | TempCelsius | temp_celsius |
| SnakeCaseUpper* | 单词用下划线分隔。 所有字符均为大写。 | TempCelsius | TEMP_CELSIUS |
- 输出人类更友好格式
using demo;
using System.Text.Json;
using System.Text.Json.Serialization;
var weather = new WeatherForecast()
{
Date = DateTimeOffset.Now,
TemperatureCelsius = 25,
Summary = "Sunny",
WindSpeed = 10
};
var jsonoptions = new JsonSerializerOptions
{
WriteIndented = true
};
var json = JsonSerializer.Serialize(weather, jsonoptions);
Console.WriteLine(json);
输出:
{
"Date": "2025-06-23T02:10:26.5399846+08:00",
"TemperatureCelsius": 25,
"Summary": "Sunny",
"Wind": 10
}
而不是:
{"Date":"2025-06-23T02:12:01.0235206+08:00","TemperatureCelsius":25,"Summary":"Sunny","Wind":10}
用在控制台或者日志输出中使人更可读'
- 忽略属性:即不参与序列化与反序列化
public class WeatherForecastWithIgnoreAttribute
{
public DateTimeOffset Date { get; set; }
public int TemperatureCelsius { get; set; }
[JsonIgnore]
public string? Summary { get; set; }
}
输出:
{
"Date": "2019-08-01T00:00:00-07:00",
"TemperatureCelsius": 25,
//缺失了Summary
}
- 包含字段
默认情况下,字段不会序列化,默认序列化与反序列化属性
//1. 使用特性的方式
public class Forecast2
{
[JsonInclude]
public DateTime Date;
[JsonInclude]
public int TemperatureC;
[JsonInclude]
public string? Summary;
}
//2. 使用JsonSerializerOptions.IncludeFields全局设置
拓展学习🎉🎉
更多的请参见微软的官方文档:
.NET中的JSON序列化和反序列化