如何将 JSON 读取为 .NET 对象(反序列化)
本文演示如何使用 System.Text.Json 命名空间从 JavaScript 对象表示法 (JSON) 进行反序列化。 如果要从 Newtonsoft.Json
移植现有代码,请参阅如何迁移到 System.Text.Json
。
反初始化 JSON 的常用方法是创建一个 .NET 类,使其包含属性和表示一个或多个 JSON 属性的字段。 接着,若要从字符串或文件进行反序列化,请调用 JsonSerializer.Deserialize 方法。 对于泛型重载,.NET 类是泛型类型参数。 对于非泛型重载,传递类的类型作为方法参数。 可以以同步或异步方式反初始化。
提示
可以使用 AI 协助,使用 GitHub Copilot 反序列化 JSON 字符串。
会默认忽略类中未表示的任何 JSON 属性。 此外,如果类型上的任何属性是必需的,但不存在于 JSON 有效负载中,反序列化将失败。
示例
以下示例演示如何对 JSON 字符串进行反初始化:
using System.Text.Json;
namespace DeserializeExtra
{
public class WeatherForecast
{
public DateTimeOffset Date { get; set; }
public int TemperatureCelsius { get; set; }
public string? Summary { get; set; }
public string? SummaryField;
public IList<DateTimeOffset>? DatesAvailable { get; set; }
public Dictionary<string, HighLowTemps>? TemperatureRanges { get; set; }
public string[]? SummaryWords { get; set; }
}
public class HighLowTemps
{
public int High { get; set; }
public int Low { get; set; }
}
public class Program
{
public static void Main()
{
string jsonString =
"""
{
"Date": "2019-08-01T00:00:00-07:00",
"TemperatureCelsius": 25,
"Summary": "Hot",
"DatesAvailable": [
"2019-08-01T00:00:00-07:00",
"2019-08-02T00:00:00-07:00"
],
"TemperatureRanges": {
"Cold": {
"High": 20,
"Low": -10
},
"Hot": {
"High": 60,
"Low": 20
}
},
"SummaryWords": [
"Cool",
"Windy",
"Humid"
]
}
""";
WeatherForecast? weatherForecast =
JsonSerializer.Deserialize<WeatherForecast>(jsonString);
Console.WriteLine($"Date: {weatherForecast?.Date}");
Console.WriteLine($"TemperatureCelsius: {weatherForecast?.TemperatureCelsius}");
Console.WriteLine($"Summary: {weatherForecast?.Summary}");
}
}
}
// output:
//Date: 8/1/2019 12:00:00 AM -07:00
//TemperatureCelsius: 25
//Summary: Hot
weatherForecast = JsonSerializer.Deserialize(Of WeatherForecastWithPOCOs)(jsonString)
若要使用同步代码从文件进行反序列化,请将文件读入字符串中,如下面的示例中所示:
using System.Text.Json;
namespace DeserializeFromFile
{
public class WeatherForecast
{
public DateTimeOffset Date { get; set; }
public int TemperatureCelsius { get; set; }
public string? Summary { get; set; }
}
public class Program
{
public static void Main()
{
string fileName = "WeatherForecast.json";
string jsonString = File.ReadAllText(fileName);
WeatherForecast weatherForecast = JsonSerializer.Deserialize<WeatherForecast>(jsonString)!;
Console.WriteLine($"Date: {weatherForecast.Date}");
Console.WriteLine($"TemperatureCelsius: {weatherForecast.TemperatureCelsius}");
Console.WriteLine($"Summary: {weatherForecast.Summary}");
}
}
}
// output:
//Date: 8/1/2019 12:00:00 AM -07:00
//TemperatureCelsius: 25
//Summary: Hot
jsonString = File.ReadAllText(fileName)
weatherForecast1 = JsonSerializer.Deserialize(Of WeatherForecast)(jsonString)
若要使用异步代码从文件进行反序列化,请调用 DeserializeAsync 方法:
using System.Text.Json;
namespace DeserializeFromFileAsync
{
public class WeatherForecast
{
public DateTimeOffset Date { get; set; }
public int TemperatureCelsius { get; set; }
public string? Summary { get; set; }
}
public class Program
{
public static async Task Main()
{
string fileName = "WeatherForecast.json";
using FileStream openStream = File.OpenRead(fileName);
WeatherForecast? weatherForecast =
await JsonSerializer.DeserializeAsync<WeatherForecast>(openStream);
Console.WriteLine($"Date: {weatherForecast?.Date}");
Console.WriteLine($"TemperatureCelsius: {weatherForecast?.TemperatureCelsius}");
Console.WriteLine($"Summary: {weatherForecast?.Summary}");
}
}
}
// output:
//Date: 8/1/2019 12:00:00 AM -07:00
//TemperatureCelsius: 25
//Summary: Hot
Dim openStream As FileStream = File.OpenRead(fileName)
weatherForecast1 = Await JsonSerializer.DeserializeAsync(Of WeatherForecast)(openStream)
反序列化行为
对 JSON 进行反序列化时,以下行为适用:
- 默认情况下,属性名称匹配区分大小写。 可以指定不区分大小写。
- 序列化程序会忽略非公共构造函数。
- 支持反序列化为不可变对象或不具有公共
set
访问器的属性,但默认未启用。 请参阅不可变类型和记录。 - 默认情况下,支持将枚举作为数字。 可以反序列化字符串枚举字段。
- 默认情况下忽略字段。 可以包含字段。
- 默认情况下,JSON 中的注释或尾随逗号会引发异常。 可以允许注释和尾随逗号。
- 默认最大深度为 64。
当你在 ASP.NET Core 应用中间接使用 System.Text.Json 时,某些默认行为会有所不同。 有关详细信息,请参阅 JsonSerializerOptions 的 Web 默认值。
可以实现自定义转换器以提供内置转换器不支持的功能。
不使用 .NET 类进行反序列化
如果有要反序列化的 JSON,但没有反序列化的目标类,则除了手动创建所需的类外,还有其他选项:
直接使用 Utf8JsonReader。
反序列化为文档对象模型 (JSON DOM),并从 DOM 中提取所需的内容。
DOM 允许你导航到 JSON 有效负载的子节,并反序列化单个值、自定义类型或数组。 有关 JsonNode DOM 的信息,请参阅反序列化 JSON 有效负载的子节。 有关 JsonDocument DOM 的详细信息,请参阅如何搜索子元素的 JsonDocument 和 JsonElement。
使用 Visual Studio 2022 自动生成所需的类:
- 复制需要反序列化的 JSON。
- 创建一个类文件并删除模板代码。
- 选择编辑>选择性粘贴>将 JSON 粘贴为类。
结果是可用于反序列化目标的类。
从 UTF-8 进行反序列化
若要从 UTF-8 进行反序列化,请调用采用 JsonSerializer.Deserialize 或 ReadOnlySpan<byte>
的 Utf8JsonReader
重载,如下面的示例中所示。 这些示例假设 JSON 处于名为 jsonUtf8Bytes 的字节数组中。
var readOnlySpan = new ReadOnlySpan<byte>(jsonUtf8Bytes);
WeatherForecast deserializedWeatherForecast =
JsonSerializer.Deserialize<WeatherForecast>(readOnlySpan)!;
Dim jsonString = Encoding.UTF8.GetString(jsonUtf8Bytes)
weatherForecast1 = JsonSerializer.Deserialize(Of WeatherForecast)(jsonString)
var utf8Reader = new Utf8JsonReader(jsonUtf8Bytes);
WeatherForecast deserializedWeatherForecast =
JsonSerializer.Deserialize<WeatherForecast>(ref utf8Reader)!;
' This code example doesn't apply to Visual Basic. For more information, go to the following URL:
' https://learn.microsoft.com/dotnet/standard/serialization/system-text-json-how-to#visual-basic-support
使用 GitHub Copilot 反序列化 JSON
可以在 IDE 中使用 GitHub Copilot,生成 System.Text.Json
以从 JSON 反序列化。 可以自定义提示以将 JSON 字符串与符合要求的属性名称和值一起使用。
以下文本显示了 Copilot 聊天的示例提示:
Generate code to use System.Text.Json to deserialize a JSON string {"FirstName":"John","LastName":"Doe","Age":30} to an equivalent .NET object.
Map property names & values.
Provide example output.
GitHub Copilot 由 AI 提供支持,因此可能会带来意外和错误。 有关详细信息,请参阅 Copilot 常见问题解答。
了解有关 Visual Studio 中的 GitHub Copilot 和 VS Code 中的 GitHub Copilot 的更多信息。