次の方法で共有


JSON を .NET オブジェクトとして読み取る方法 (逆シリアル化)

この記事では、System.Text.Json 名前空間を使用して JavaScript Object Notation (JSON) の逆シリアル化を行う方法をご紹介します。 Newtonsoft.Json から既存のコードを移植する場合は、Newtonsoft.Jsonに関する記事を参照してください。

JSON を逆シリアル化する一般的な方法は、1 つまたは複数の JSON プロパティを表すプロパティとフィールドを持つ .NET クラスを作成することです。 その後、文字列またはファイルから逆シリアル化するには、JsonSerializer.Deserialize メソッドを呼び出します。 ジェネリック オーバーロードの場合、ジェネリック型パラメーターは .NET クラスです。 非ジェネリック オーバーロードの場合は、クラスの型をメソッド パラメーターとして渡します。 同期または非同期のいずれかで逆シリアル化することができます。

ヒント

AI アシスタンスを使用して 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 を逆シリアル化する場合、次の動作が適用されます。

ASP.NET Core アプリで System.Text.Json を間接的に使用する場合、一部の既定の動作が異なります。 詳細については、「JsonSerializerOptions の Web の規定値」を参照してください。

カスタム コンバーターを実装して、組み込みコンバーターではサポートされていない機能を提供できます。

.NET クラスを使用せずに逆シリアル化する

逆シリアル化する JSON があり、それを逆シリアル化するクラスがない場合は、必要なクラスを手動で作成する以外のオプションがあります。

  • Utf8JsonReader を直接使用します。

  • JSON DOM (ドキュメント オブジェクト モデル) に逆シリアル化し、DOM から必要なデータを抽出します。

    DOM を使用すると、JSON ペイロードのサブセクションに移動し、単一の値、カスタム型、または配列を逆シリアル化できます。 JsonNode DOM の詳細については、「JSON ペイロードのサブセクションを逆シリアル化する」を参照してください。 JsonDocument DOM の詳細については、「JsonDocument」を参照してください。

  • 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

AI を使用して JSON を逆シリアル化する

GitHub Copilot などの AI ツールを使用して、を使用して 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 の FAQ を参照 してください

こちらも参照ください