JsonSerializerOptions-exemplaren instantiëren met System.Text.Json
In dit artikel wordt uitgelegd hoe u prestatieproblemen kunt voorkomen wanneer u gebruikt JsonSerializerOptions. Ook ziet u hoe u de parameters gebruikt die beschikbaar zijn.
JsonSerializerOptions-exemplaren opnieuw gebruiken
Als u herhaaldelijk met dezelfde opties gebruikt JsonSerializerOptions
, maakt u niet telkens een nieuw JsonSerializerOptions
exemplaar wanneer u deze gebruikt. Gebruik dezelfde instantie voor elke aanroep opnieuw. Deze richtlijnen zijn van toepassing op code die u schrijft voor aangepaste conversieprogramma's en wanneer u aanroept JsonSerializer.Serialize of JsonSerializer.Deserialize. Het is veilig om hetzelfde exemplaar te gebruiken voor meerdere threads. De metagegevenscaches op het optiesexemplaren zijn thread-safe en het exemplaar is onveranderbaar na de eerste serialisatie of deserialisatie.
In de volgende code ziet u de prestatiestraf voor het gebruik van nieuwe opties.
using System.Diagnostics;
using System.Text.Json;
namespace OptionsPerfDemo
{
public record Forecast(DateTime Date, int TemperatureC, string Summary);
public class Program
{
public static void Main()
{
Forecast forecast = new(DateTime.Now, 40, "Hot");
JsonSerializerOptions options = new() { WriteIndented = true };
int iterations = 100000;
var watch = Stopwatch.StartNew();
for (int i = 0; i < iterations; i++)
{
Serialize(forecast, options);
}
watch.Stop();
Console.WriteLine($"Elapsed time using one options instance: {watch.ElapsedMilliseconds}");
watch = Stopwatch.StartNew();
for (int i = 0; i < iterations; i++)
{
Serialize(forecast);
}
watch.Stop();
Console.WriteLine($"Elapsed time creating new options instances: {watch.ElapsedMilliseconds}");
}
private static void Serialize(Forecast forecast, JsonSerializerOptions? options = null)
{
_ = JsonSerializer.Serialize<Forecast>(
forecast,
options ?? new JsonSerializerOptions() { WriteIndented = true });
}
}
}
// Produces output like the following example:
//
//Elapsed time using one options instance: 190
//Elapsed time creating new options instances: 40140
Met de voorgaande code wordt een klein object 100.000 keer geserialiseerd met dezelfde instantie van opties. Vervolgens wordt hetzelfde object hetzelfde aantal keren geserialiseerd en wordt elke keer een nieuw exemplaar van opties gemaakt. Een typisch uitvoeringstijdverschil is 190 in vergelijking met 40.140 milliseconden. Het verschil is nog groter als u het aantal iteraties verhoogt.
De serializer ondergaat een opwarmfase tijdens de eerste serialisatie van elk type in de objectgrafiek wanneer er een nieuw exemplaar van opties aan wordt doorgegeven. Deze opwarmer omvat het maken van een cache met metagegevens die nodig zijn voor serialisatie. De metagegevens omvatten gemachtigden voor eigenschaps getters, setters, constructorargumenten, opgegeven kenmerken, enzovoort. Deze metagegevenscache wordt opgeslagen in het optiesexemplaren. Hetzelfde opwarmproces en dezelfde cache zijn van toepassing op deserialisatie.
De grootte van de metagegevenscache in een JsonSerializerOptions
exemplaar is afhankelijk van het aantal typen dat moet worden geserialiseerd. Als u meerdere typen doorgeeft, bijvoorbeeld dynamisch gegenereerde typen, blijft de cachegrootte toenemen en kan dit een gevolg zijn van een OutOfMemoryException
.
De JsonSerializerOptions.Default
eigenschap
Als het exemplaar dat JsonSerializerOptions
u moet gebruiken het standaardexemplaren is (met alle standaardinstellingen en de standaardconversieprogramma's), gebruikt u de JsonSerializerOptions.Default eigenschap in plaats van een exemplaar van opties te maken. Zie Standaardsysteemconversieprogramma gebruiken voor meer informatie.
JsonSerializerOptions kopiëren
Er is een JsonSerializerOptions-constructor waarmee u een nieuw exemplaar kunt maken met dezelfde opties als een bestaand exemplaar, zoals wordt weergegeven in het volgende voorbeeld:
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"
'}
De metagegevenscache van het bestaande JsonSerializerOptions
exemplaar wordt niet gekopieerd naar het nieuwe exemplaar. Het gebruik van deze constructor is dus niet hetzelfde als het hergebruiken van een bestaand exemplaar van JsonSerializerOptions
.
Webstandaarden voor JsonSerializerOptions
De volgende opties hebben verschillende standaardwaarden voor web-apps:
- PropertyNameCaseInsensitive =
true
- PropertyNamingPolicy = CamelCase
- NumberHandling = AllowReadingFromString
In .NET 9 en latere versies kunt u de JsonSerializerOptions.Web singleton gebruiken om te serialiseren met de standaardopties die ASP.NET Core gebruikt voor web-apps. Roep in eerdere versies de JsonSerializerOptions-constructor aan om een nieuw exemplaar te maken met de webstandaarden, zoals wordt weergegeven in het volgende voorbeeld:
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