如何将 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 进行反序列化时,以下行为适用:

当你在 ASP.NET Core 应用中间接使用 System.Text.Json 时,某些默认行为会有所不同。 有关详细信息,请参阅 JsonSerializerOptions 的 Web 默认值

可以实现自定义转换器以提供内置转换器不支持的功能。

不使用 .NET 类进行反序列化

如果有要反序列化的 JSON,但没有反序列化的目标类,则除了手动创建所需的类外,还有其他选项:

从 UTF-8 进行反序列化

若要从 UTF-8 进行反序列化,请调用采用 JsonSerializer.DeserializeReadOnlySpan<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 CopilotVS Code 中的 GitHub Copilot 的更多信息。