この記事では、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 を逆シリアル化する場合、次の動作が適用されます。
- 既定では、プロパティ名の照合では大文字と小文字が区別されます。 大文字と小文字を区別しないことを指定できます。
- 非パブリック コンストラクターはシリアライザーにより無視されます。
- パブリック
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」を参照してください。
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 を参照 してください。
こちらも参照ください
.NET