System.Text.Json で JsonSerializerOptions インスタンスをインスタンス化する方法
この記事では、JsonSerializerOptions の使用時にパフォーマンスの問題を回避する方法について説明します。 また、使用可能なパラメーター化コンストラクターの使用方法についても説明します。
JsonSerializerOptions インスタンスの再利用
同じオプションで JsonSerializerOptions
を繰り返し使用する場合、使用のたびに新しい JsonSerializerOptions
インスタンスを作成しないでください。 すべての呼び出しで同じインスタンスを再利用します。 ここでは、カスタム コンバーター用に作成し、JsonSerializer.Serialize または JsonSerializer.Deserialize を呼び出すコードに関して説明しています。 複数のスレッドで同じインスタンスを使用することに問題はありません。 オプション インスタンス上のメタデータ キャッシュはスレッドセーフであり、最初のシリアル化または逆シリアル化を行うと、その後はインスタンスを変更できなくなります。
JsonSerializerOptions.Default
プロパティ
使用する必要がある JsonSerializerOptions
のインスタンスが既定のインスタンスである (既定の設定と既定のコンバーターをすべて備えている) 場合は、オプションのインスタンスを作成するのではなく、JsonSerializerOptions.Default プロパティを使用します。 詳細については、「既定のシステム コンバーターを使用する」を参照してください。
JsonSerializerOptions をコピーする
次の例で示すように、JsonSerializerOptions constructor を使用すると、既存のインスタンスと同じオプションを使用して、新しいインスタンスを作成できます。
using System.Text.Json;
namespace CopyOptions
{
public class Forecast
{
public DateTime Date { get; init; }
public int TemperatureC { get; set; }
public string? Summary { get; set; }
};
public class Program
{
public static void Main()
{
Forecast forecast = new()
{
Date = DateTime.Now,
TemperatureC = 40,
Summary = "Hot"
};
JsonSerializerOptions options = new()
{
WriteIndented = true
};
JsonSerializerOptions optionsCopy = new(options);
string forecastJson =
JsonSerializer.Serialize<Forecast>(forecast, optionsCopy);
Console.WriteLine($"Output JSON:\n{forecastJson}");
}
}
}
// Produces output like the following example:
//
//Output JSON:
//{
// "Date": "2020-10-21T15:40:06.8998502-07:00",
// "TemperatureC": 40,
// "Summary": "Hot"
//}
Imports System.Text.Json
Imports System.Text.Json.Serialization
Namespace CopyOptions
Public Class Forecast
Public Property [Date] As Date
Public Property TemperatureC As Integer
Public Property Summary As String
End Class
Public NotInheritable Class Program
Public Shared Sub Main()
Dim forecast1 As New Forecast() With {
.[Date] = Date.Now,
.Summary = Nothing,
.TemperatureC = CType(Nothing, Integer)
}
Dim options As New JsonSerializerOptions() With {
.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault
}
Dim optionsCopy As New JsonSerializerOptions
Dim forecastJson As String = JsonSerializer.Serialize(forecast1, optionsCopy)
Console.WriteLine($"Output JSON:{forecastJson}")
End Sub
End Class
End Namespace
' Produces output like the following example:
'
'Output JSON:
'{
' "Date": "2020-10-21T15:40:06.8998502-07:00",
' "TemperatureC": 40,
' "Summary": "Hot"
'}
既存の JsonSerializerOptions
インスタンスのメタデータ キャッシュは、新しいインスタンスにはコピーされません。 そのため、このコンストラクターを使用することは、既存の JsonSerializerOptions
のインスタンスを再利用することと同じではありません。
JsonSerializerOptions の Web の既定値
次のオプションでは、Web アプリの既定値が異なります。
- PropertyNameCaseInsensitive =
true
- PropertyNamingPolicy = CamelCase
- NumberHandling = AllowReadingFromString
.NET 9 以降のバージョンでは、JsonSerializerOptions.Web シングルトンを使って、ASP.NET Core が Web アプリに使う既定のオプションでシリアル化できます。 以前のバージョンでは、次の例に示すように、JsonSerializerOptions コンストラクターを呼び出して、Web 既定値を使って新しいインスタンスを作成します。
using System.Text.Json;
namespace OptionsDefaults
{
public class Forecast
{
public DateTime? Date { get; init; }
public int TemperatureC { get; set; }
public string? Summary { get; set; }
};
public class Program
{
public static void Main()
{
Forecast forecast = new()
{
Date = DateTime.Now,
TemperatureC = 40,
Summary = "Hot"
};
JsonSerializerOptions options = new(JsonSerializerDefaults.Web)
{
WriteIndented = true
};
Console.WriteLine(
$"PropertyNameCaseInsensitive: {options.PropertyNameCaseInsensitive}");
Console.WriteLine(
$"JsonNamingPolicy: {options.PropertyNamingPolicy}");
Console.WriteLine(
$"NumberHandling: {options.NumberHandling}");
string forecastJson = JsonSerializer.Serialize<Forecast>(forecast, options);
Console.WriteLine($"Output JSON:\n{forecastJson}");
Forecast? forecastDeserialized =
JsonSerializer.Deserialize<Forecast>(forecastJson, options);
Console.WriteLine($"Date: {forecastDeserialized?.Date}");
Console.WriteLine($"TemperatureC: {forecastDeserialized?.TemperatureC}");
Console.WriteLine($"Summary: {forecastDeserialized?.Summary}");
}
}
}
// Produces output like the following example:
//
//PropertyNameCaseInsensitive: True
//JsonNamingPolicy: System.Text.Json.JsonCamelCaseNamingPolicy
//NumberHandling: AllowReadingFromString
//Output JSON:
//{
// "date": "2020-10-21T15:40:06.9040831-07:00",
// "temperatureC": 40,
// "summary": "Hot"
//}
//Date: 10 / 21 / 2020 3:40:06 PM
//TemperatureC: 40
//Summary: Hot
Imports System.Text.Json
Namespace OptionsDefaults
Public Class Forecast
Public Property [Date] As Date
Public Property TemperatureC As Integer
Public Property Summary As String
End Class
Public NotInheritable Class Program
Public Shared Sub Main()
Dim forecast1 As New Forecast() With {
.[Date] = Date.Now,
.TemperatureC = 40,
.Summary = "Hot"
}
Dim options As New JsonSerializerOptions(JsonSerializerDefaults.Web) With {
.WriteIndented = True
}
Console.WriteLine(
$"PropertyNameCaseInsensitive: {options.PropertyNameCaseInsensitive}")
Console.WriteLine(
$"JsonNamingPolicy: {options.PropertyNamingPolicy}")
Console.WriteLine(
$"NumberHandling: {options.NumberHandling}")
Dim forecastJson As String = JsonSerializer.Serialize(forecast1, options)
Console.WriteLine($"Output JSON:{forecastJson}")
Dim forecastDeserialized As Forecast = JsonSerializer.Deserialize(Of Forecast)(forecastJson, options)
Console.WriteLine($"Date: {forecastDeserialized.[Date]}")
Console.WriteLine($"TemperatureC: {forecastDeserialized.TemperatureC}")
Console.WriteLine($"Summary: {forecastDeserialized.Summary}")
End Sub
End Class
End Namespace
' Produces output like the following example:
'
'PropertyNameCaseInsensitive: True
'JsonNamingPolicy: System.Text.Json.JsonCamelCaseNamingPolicy
'NumberHandling: AllowReadingFromString
'Output JSON:
'{
' "date": "2020-10-21T15:40:06.9040831-07:00",
' "temperatureC": 40,
' "summary": "Hot"
'}
'Date: 10 / 21 / 2020 3:40:06 PM
'TemperatureC: 40
'Summary: Hot
.NET