Как считать JSON как объекты .NET (десериализация)

В этой статье показано, как использовать System.Text.Json пространство имен для десериализации из нотации объектов JavaScript (JSON). Если вы переносите существующий код из Newtonsoft.Json, ознакомьтесь со статьей Как перейти на System.Text.Json.

Общий способ десериализации JSON — иметь (или создать) класс .NET со свойствами и полями, представляющими одно или несколько свойств JSON. Затем для десериализации из строки или файла вызовите JsonSerializer.Deserialize метод. Для обобщённых перегрузок параметр обобщённого типа является классом .NET. Для необобщённых перегрузок передайте тип класса в качестве параметра метода. Десериализировать можно синхронно или асинхронно.

Совет

Вы можете использовать помощь ИИ для десериализации строки 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}");

            if (weatherForecast?.DatesAvailable != null)
            {
                foreach (DateTimeOffset dateTimeOffset in weatherForecast.DatesAvailable)
                {
                    Console.WriteLine($"DateAvailable: {dateTimeOffset}");
                }
            }

            if (weatherForecast?.TemperatureRanges != null)
            {
                foreach (KeyValuePair<string, HighLowTemps> temperatureRange in weatherForecast.TemperatureRanges)
                {
                    Console.WriteLine($"TemperatureRange: {temperatureRange.Key} is {temperatureRange.Value.Low} to {temperatureRange.Value.High}");
                }
            }

            if (weatherForecast?.SummaryWords != null)
            {
                foreach (string summaryWord in weatherForecast.SummaryWords)
                {
                    Console.WriteLine($"SummaryWord: {summaryWord}");
                }
            }
        }
    }
}

/* Output:
 * 
 * Date: 8/1/2019 12:00:00 AM -07:00
 * TemperatureCelsius: 25
 * Summary: Hot
 * DateAvailable: 8/1/2019 12:00:00 AM -07:00
 * DateAvailable: 8/2/2019 12:00:00 AM -07:00
 * TemperatureRange: Cold is -10 to 20
 * TemperatureRange: Hot is 20 to 60
 * SummaryWord: Cool
 * SummaryWord: Windy
 * SummaryWord: Humid
 * */
Imports System.Text.Json

Namespace DeserializeExtra

    Public Class WeatherForecast
        Public Property [Date] As DateTimeOffset
        Public Property TemperatureCelsius As Integer
        Public Property Summary As String
        Public SummaryField As String
        Public Property DatesAvailable As IList(Of DateTimeOffset)
        Public Property TemperatureRanges As Dictionary(Of String, HighLowTemps)
        Public Property SummaryWords As String()
    End Class

    Public Class HighLowTemps
        Public Property High As Integer
        Public Property Low As Integer
    End Class

    Public NotInheritable Class Program

        Public Shared Sub Run()
            Dim jsonString As String =
                "{
                  ""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""
                  ]
                }"

            Dim weatherForecast As WeatherForecast =
                JsonSerializer.Deserialize(Of WeatherForecast)(jsonString)

            Console.WriteLine($"Date: {weatherForecast?.Date}")
            Console.WriteLine($"TemperatureCelsius: {weatherForecast?.TemperatureCelsius}")
            Console.WriteLine($"Summary: {weatherForecast?.Summary}")

            If weatherForecast?.DatesAvailable IsNot Nothing Then
                For Each dateTimeOffset As DateTimeOffset In weatherForecast.DatesAvailable
                    Console.WriteLine($"DateAvailable: {dateTimeOffset}")
                Next
            End If

            If weatherForecast?.TemperatureRanges IsNot Nothing Then
                For Each temperatureRange As KeyValuePair(Of String, HighLowTemps) In weatherForecast.TemperatureRanges
                    Console.WriteLine($"TemperatureRange: {temperatureRange.Key} is {temperatureRange.Value.Low} to {temperatureRange.Value.High}")
                Next
            End If

            If weatherForecast?.SummaryWords IsNot Nothing Then
                For Each summaryWord As String In weatherForecast.SummaryWords
                    Console.WriteLine($"SummaryWord: {summaryWord}")
                Next
            End If
        End Sub

    End Class

End Namespace

' Output:
'
'Date: 8/1/2019 12:00:00 AM -07:00
'TemperatureCelsius: 25
'Summary: Hot
'DateAvailable: 8/1/2019 12:00:00 AM -07:00
'DateAvailable: 8/2/2019 12:00:00 AM -07:00
'TemperatureRange: Cold is -10 to 20
'TemperatureRange: Hot is 20 to 60
'SummaryWord: Cool
'SummaryWord: Windy
'SummaryWord: Humid

Чтобы выполнить десериализацию из файла с помощью синхронного кода, выполните считывание файла в строку, как показано в следующем примере:

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 применяются следующие правила поведения:

При косвенном использовании System.Text.Json в приложении ASP.NET Core некоторые поведения по умолчанию отличаются. Дополнительные сведения см. в разделе Стандартные параметры веб-приложений для JsonSerializerOptions.

Для обеспечения функциональности, которая не поддерживается встроенными преобразователями, можно реализовать пользовательские преобразователи.

Десериализация без использования класса .NET

Если у вас есть JSON, который вы хотите десериализовать, но при этом у вас нет класса, в который его можно десериализовать, у вас есть варианты, помимо ручного создания нужного класса:

  • Используйте Utf8JsonReader напрямую.

  • Десериализовать в JSON DOM (объектную модель документа) и извлечь из DOM необходимые данные.

    DOM позволяет перейти к подразделу JSON-данных и десериализировать одно значение, пользовательский тип или массив. Сведения о 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

Использование ИИ для десериализации JSON

Вы можете использовать средства ИИ, такие как GitHub Copilot, для создания кода, который использует System.Text.Json для десериализации из JSON. Например, можно настроить запрос, чтобы продемонстрировать десериализацию, когда целевой класс определяет свойство, отсутствующее во входных данных JSON.

В следующем тексте показан пример запроса для Copilot Chat:

Generate C# code to use System.Text.Json to deserialize a JSON string {"FirstName":"John","LastName":"Doe"} to an equivalent .NET object, where the class defines an Age property.
Show what happens when the JSON is missing a property defined in the class.
Provide example output.

Ознакомьтесь с предложениями Copilot, прежде чем применять их.

Дополнительные сведения о GitHub Copilot см. в часто задаваемых вопросых о GitHub.

См. также