Jak używać dokumentu JSON, Utf8JsonReader i Utf8JsonWriter w programie System.Text.Json
W tym artykule pokazano, jak używać następujących sposobów:
- Model obiektów dokumentów JSON (DOM) na potrzeby losowego dostępu do danych w ładunku JSON.
- Typ
Utf8JsonWriterkompilowania niestandardowych serializatorów. - Typ
Utf8JsonReadertworzenia niestandardowych parserów i deserializacji.
Opcje DOM w formacie JSON
Praca z dom jest alternatywą dla deserializacji za pomocą polecenia JsonSerializer:
- Jeśli nie masz typu do deserializacji.
- Gdy otrzymany kod JSON nie ma stałego schematu i musi zostać sprawdzony, aby wiedzieć, co zawiera.
System.Text.Json Udostępnia dwa sposoby tworzenia modelu DOM w formacie JSON:
- JsonDocument zapewnia możliwość tworzenia modelu DOM tylko do odczytu przy użyciu polecenia
Utf8JsonReader. Dostęp do elementów JSON, które tworzą ładunek, można uzyskać za pośrednictwem JsonElement typu. TypJsonElementudostępnia moduły wyliczania tablic i obiektów wraz z interfejsami API, aby przekonwertować tekst JSON na typowe typy platformy .NET.JsonDocumentuwidacznia RootElement właściwość. Aby uzyskać więcej informacji, zobacz Używanie narzędzia JsonDocument w dalszej części tego artykułu.
- JsonNode a klasy pochodzące z niej w System.Text.Json.Nodes przestrzeni nazw zapewniają możliwość utworzenia niezmiennego MODELU DOM. Dostęp do elementów JSON, które tworzą ładunek, można uzyskać za pośrednictwem JsonNodetypów , JsonObject, JsonArray, JsonValuei JsonElement . Aby uzyskać więcej informacji, zobacz Używanie
JsonNodew dalszej części tego artykułu.
Podczas wybierania opcji JsonDocument i JsonNodeuwzględnienia następujących czynników należy wziąć pod uwagę następujące czynniki:
- Dom
JsonNodemożna zmienić po jego utworzeniu. DOMJsonDocumentjest niezmienny. - Dom
JsonDocumentzapewnia szybszy dostęp do danych.
- Począwszy od platformy .NET 6, JsonNode a klasy pochodzące z niej w System.Text.Json.Nodes przestrzeni nazw zapewniają możliwość tworzenia niezmiennego modelu DOM. Aby uzyskać więcej informacji, zobacz wersję platformy .NET 6 tego artykułu.
Korzystanie z polecenia JsonNode
W poniższym przykładzie pokazano, jak używać JsonNode i innych typów w System.Text.Json.Nodes przestrzeni nazw do:
- Tworzenie modelu DOM na podstawie ciągu JSON
- Napisz kod JSON z modelu DOM.
- Pobierz wartość, obiekt lub tablicę z modelu DOM.
using System.Text.Json;
using System.Text.Json.Nodes;
namespace JsonNodeFromStringExample;
public class Program
{
public static void Main()
{
string jsonString =
@"{
""Date"": ""2019-08-01T00:00:00"",
""Temperature"": 25,
""Summary"": ""Hot"",
""DatesAvailable"": [
""2019-08-01T00:00:00"",
""2019-08-02T00:00:00""
],
""TemperatureRanges"": {
""Cold"": {
""High"": 20,
""Low"": -10
},
""Hot"": {
""High"": 60,
""Low"": 20
}
}
}
";
// Create a JsonNode DOM from a JSON string.
JsonNode forecastNode = JsonNode.Parse(jsonString)!;
// Write JSON from a JsonNode
var options = new JsonSerializerOptions { WriteIndented = true };
Console.WriteLine(forecastNode!.ToJsonString(options));
// output:
//{
// "Date": "2019-08-01T00:00:00",
// "Temperature": 25,
// "Summary": "Hot",
// "DatesAvailable": [
// "2019-08-01T00:00:00",
// "2019-08-02T00:00:00"
// ],
// "TemperatureRanges": {
// "Cold": {
// "High": 20,
// "Low": -10
// },
// "Hot": {
// "High": 60,
// "Low": 20
// }
// }
//}
// Get value from a JsonNode.
JsonNode temperatureNode = forecastNode!["Temperature"]!;
Console.WriteLine($"Type={temperatureNode.GetType()}");
Console.WriteLine($"JSON={temperatureNode.ToJsonString()}");
//output:
//Type = System.Text.Json.Nodes.JsonValue`1[System.Text.Json.JsonElement]
//JSON = 25
// Get a typed value from a JsonNode.
int temperatureInt = (int)forecastNode!["Temperature"]!;
Console.WriteLine($"Value={temperatureInt}");
//output:
//Value=25
// Get a typed value from a JsonNode by using GetValue<T>.
temperatureInt = forecastNode!["Temperature"]!.GetValue<int>();
Console.WriteLine($"TemperatureInt={temperatureInt}");
//output:
//Value=25
// Get a JSON object from a JsonNode.
JsonNode temperatureRanges = forecastNode!["TemperatureRanges"]!;
Console.WriteLine($"Type={temperatureRanges.GetType()}");
Console.WriteLine($"JSON={temperatureRanges.ToJsonString()}");
//output:
//Type = System.Text.Json.Nodes.JsonObject
//JSON = { "Cold":{ "High":20,"Low":-10},"Hot":{ "High":60,"Low":20} }
// Get a JSON array from a JsonNode.
JsonNode datesAvailable = forecastNode!["DatesAvailable"]!;
Console.WriteLine($"Type={datesAvailable.GetType()}");
Console.WriteLine($"JSON={datesAvailable.ToJsonString()}");
//output:
//datesAvailable Type = System.Text.Json.Nodes.JsonArray
//datesAvailable JSON =["2019-08-01T00:00:00", "2019-08-02T00:00:00"]
// Get an array element value from a JsonArray.
JsonNode firstDateAvailable = datesAvailable[0]!;
Console.WriteLine($"Type={firstDateAvailable.GetType()}");
Console.WriteLine($"JSON={firstDateAvailable.ToJsonString()}");
//output:
//Type = System.Text.Json.Nodes.JsonValue`1[System.Text.Json.JsonElement]
//JSON = "2019-08-01T00:00:00"
// Get a typed value by chaining references.
int coldHighTemperature = (int)forecastNode["TemperatureRanges"]!["Cold"]!["High"]!;
Console.WriteLine($"TemperatureRanges.Cold.High={coldHighTemperature}");
//output:
//TemperatureRanges.Cold.High = 20
// Parse a JSON array
var datesNode = JsonNode.Parse(@"[""2019-08-01T00:00:00"",""2019-08-02T00:00:00""]");
JsonNode firstDate = datesNode![0]!.GetValue<DateTime>();
Console.WriteLine($"firstDate={ firstDate}");
//output:
//firstDate = "2019-08-01T00:00:00"
}
}
Tworzenie obiektu DOM JsonNode za pomocą inicjatorów obiektów i wprowadzanie zmian
W poniższym przykładzie pokazano, jak:
- Utwórz dom przy użyciu inicjatorów obiektów.
- Wprowadź zmiany w modelu DOM.
using System.Text.Json;
using System.Text.Json.Nodes;
namespace JsonNodeFromObjectExample;
public class Program
{
public static void Main()
{
// Create a new JsonObject using object initializers.
var forecastObject = new JsonObject
{
["Date"] = new DateTime(2019, 8, 1),
["Temperature"] = 25,
["Summary"] = "Hot",
["DatesAvailable"] = new JsonArray(
new DateTime(2019, 8, 1), new DateTime(2019, 8, 2)),
["TemperatureRanges"] = new JsonObject
{
["Cold"] = new JsonObject
{
["High"] = 20,
["Low"] = -10
}
},
["SummaryWords"] = new JsonArray("Cool", "Windy", "Humid")
};
// Add an object.
forecastObject!["TemperatureRanges"]!["Hot"] =
new JsonObject { ["High"] = 60, ["Low"] = 20 };
// Remove a property.
forecastObject.Remove("SummaryWords");
// Change the value of a property.
forecastObject["Date"] = new DateTime(2019, 8, 3);
var options = new JsonSerializerOptions { WriteIndented = true };
Console.WriteLine(forecastObject.ToJsonString(options));
//output:
//{
// "Date": "2019-08-03T00:00:00",
// "Temperature": 25,
// "Summary": "Hot",
// "DatesAvailable": [
// "2019-08-01T00:00:00",
// "2019-08-02T00:00:00"
// ],
// "TemperatureRanges": {
// "Cold": {
// "High": 20,
// "Low": -10
// },
// "Hot": {
// "High": 60,
// "Low": 20
// }
// }
//}
}
}
Deserializowanie podsekcji ładunku JSON
W poniższym przykładzie pokazano, jak za pomocą węzła JsonNode przejść do podsekcji drzewa JSON i deserializować pojedynczą wartość, typ niestandardowy lub tablicę z tej podsekcji.
using System.Text.Json;
using System.Text.Json.Nodes;
namespace JsonNodePOCOExample;
public class TemperatureRanges : Dictionary<string, HighLowTemps>
{
}
public class HighLowTemps
{
public int High { get; set; }
public int Low { get; set; }
}
public class Program
{
public static DateTime[]? DatesAvailable { get; set; }
public static void Main()
{
string jsonString =
@"{
""Date"": ""2019-08-01T00:00:00"",
""Temperature"": 25,
""Summary"": ""Hot"",
""DatesAvailable"": [
""2019-08-01T00:00:00"",
""2019-08-02T00:00:00""
],
""TemperatureRanges"": {
""Cold"": {
""High"": 20,
""Low"": -10
},
""Hot"": {
""High"": 60,
""Low"": 20
}
}
}
";
// Parse all of the JSON.
JsonNode forecastNode = JsonNode.Parse(jsonString)!;
// Get a single value
int hotHigh = forecastNode["TemperatureRanges"]!["Hot"]!["High"]!.GetValue<int>();
Console.WriteLine($"Hot.High={hotHigh}");
// output:
//Hot.High=60
// Get a subsection and deserialize it into a custom type.
JsonObject temperatureRangesObject = forecastNode!["TemperatureRanges"]!.AsObject();
using var stream = new MemoryStream();
using var writer = new Utf8JsonWriter(stream);
temperatureRangesObject.WriteTo(writer);
writer.Flush();
TemperatureRanges? temperatureRanges =
JsonSerializer.Deserialize<TemperatureRanges>(stream.ToArray());
Console.WriteLine($"Cold.Low={temperatureRanges!["Cold"].Low}, Hot.High={temperatureRanges["Hot"].High}");
// output:
//Cold.Low=-10, Hot.High=60
// Get a subsection and deserialize it into an array.
JsonArray datesAvailable = forecastNode!["DatesAvailable"]!.AsArray()!;
Console.WriteLine($"DatesAvailable[0]={datesAvailable[0]}");
// output:
//DatesAvailable[0]=8/1/2019 12:00:00 AM
}
}
Przykład średniej klasy JsonNode
Poniższy przykład wybiera tablicę JSON zawierającą wartości całkowite i oblicza średnią wartość:
using System.Text.Json.Nodes;
namespace JsonNodeAverageGradeExample;
public class Program
{
public static void Main()
{
string jsonString =
@"{
""Class Name"": ""Science"",
""Teacher\u0027s Name"": ""Jane"",
""Semester"": ""2019-01-01"",
""Students"": [
{
""Name"": ""John"",
""Grade"": 94.3
},
{
""Name"": ""James"",
""Grade"": 81.0
},
{
""Name"": ""Julia"",
""Grade"": 91.9
},
{
""Name"": ""Jessica"",
""Grade"": 72.4
},
{
""Name"": ""Johnathan""
}
],
""Final"": true
}
";
double sum = 0;
int count = 0;
JsonNode document = JsonNode.Parse(jsonString)!;
JsonNode root = document.Root;
JsonArray studentsArray = root["Students"]!.AsArray();
count = studentsArray.Count;
foreach (JsonNode? student in studentsArray)
{
if (student?["Grade"] is JsonNode gradeNode)
{
sum += (double)gradeNode;
}
else
{
sum += 70;
}
}
double average = sum / count;
Console.WriteLine($"Average grade : {average}");
}
}
// output:
//Average grade : 81.92
Powyższy kod ma następujące działanie:
- Oblicza średnią ocenę obiektów w
Studentstablicy, która maGradewłaściwość. - Przypisuje domyślną ocenę 70 dla uczniów, którzy nie mają klasy.
- Pobiera liczbę uczniów z
CountwłaściwościJsonArray.
JsonNode Z JsonSerializerOptions
Za pomocą JsonSerializer polecenia można serializować i deserializować wystąpienie klasy JsonNode. Jednak jeśli używasz przeciążenia, które przyjmuje JsonSerializerOptions, wystąpienie opcji jest używane tylko do pobierania konwerterów niestandardowych. Inne funkcje wystąpienia opcji nie są używane. Jeśli na przykład ustawisz wartość JsonSerializerOptions.DefaultIgnoreConditionWhenWritingNull i wywołasz JsonSerializer polecenie z przeciążeniem, które przyjmuje JsonSerializerOptionswartość , właściwości null nie zostaną zignorowane.
To samo ograniczenie dotyczy JsonNode metod, które przyjmują JsonSerializerOptions parametr : WriteTo(Utf8JsonWriter, JsonSerializerOptions) i ToJsonString(JsonSerializerOptions). Te interfejsy API używają JsonSerializerOptions tylko do pobierania konwerterów niestandardowych.
Poniższy przykład ilustruje wynik użycia metod, które przyjmują JsonSerializerOptions parametr i serializują JsonNode wystąpienie:
using System.Text;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Text.Json.Serialization;
namespace JsonNodeWithJsonSerializerOptions;
public class Program
{
public static void Main()
{
Person person = new Person { Name = "Nancy" };
// Default serialization - Address property included with null token.
// Output: {"Name":"Nancy","Address":null}
string personJsonWithNull = JsonSerializer.Serialize(person);
Console.WriteLine(personJsonWithNull);
// Serialize and ignore null properties - null Address property is omitted
// Output: {"Name":"Nancy"}
JsonSerializerOptions options = new()
{
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
};
string personJsonWithoutNull = JsonSerializer.Serialize(person, options);
Console.WriteLine(personJsonWithoutNull);
// Ignore null properties doesn't work when serializing JsonNode instance
// by using JsonSerializer.
// Output: {"Name":"Nancy","Address":null}
var personJsonNode = JsonSerializer.Deserialize<JsonNode>(personJsonWithNull);
personJsonWithNull = JsonSerializer.Serialize(personJsonNode, options);
Console.WriteLine(personJsonWithNull);
// Ignore null properties doesn't work when serializing JsonNode instance
// by using JsonNode.ToJsonString method.
// Output: {"Name":"Nancy","Address":null}
personJsonWithNull = personJsonNode!.ToJsonString(options);
Console.WriteLine(personJsonWithNull);
// Ignore null properties doesn't work when serializing JsonNode instance
// by using JsonNode.WriteTo method.
// Output: {"Name":"Nancy","Address":null}
using var stream = new MemoryStream();
using var writer = new Utf8JsonWriter(stream);
personJsonNode!.WriteTo(writer, options);
writer.Flush();
personJsonWithNull = Encoding.UTF8.GetString(stream.ToArray());
Console.WriteLine(personJsonWithNull);
}
}
public class Person
{
public string? Name { get; set; }
public string? Address { get; set; }
}
Jeśli potrzebujesz funkcji JsonSerializerOptions innych niż konwertery niestandardowe, użyj JsonSerializer silnie typiowanych obiektów docelowych (takich jak Person klasa w tym przykładzie), a nie JsonNode.
Korzystanie z polecenia JsonDocument
W poniższym przykładzie pokazano, jak używać JsonDocument klasy do losowego dostępu do danych w ciągu JSON:
double sum = 0;
int count = 0;
using (JsonDocument document = JsonDocument.Parse(jsonString))
{
JsonElement root = document.RootElement;
JsonElement studentsElement = root.GetProperty("Students");
foreach (JsonElement student in studentsElement.EnumerateArray())
{
if (student.TryGetProperty("Grade", out JsonElement gradeElement))
{
sum += gradeElement.GetDouble();
}
else
{
sum += 70;
}
count++;
}
}
double average = sum / count;
Console.WriteLine($"Average grade : {average}");
Dim sum As Double = 0
Dim count As Integer = 0
Using document As JsonDocument = JsonDocument.Parse(jsonString)
Dim root As JsonElement = document.RootElement
Dim studentsElement As JsonElement = root.GetProperty("Students")
For Each student As JsonElement In studentsElement.EnumerateArray()
Dim gradeElement As JsonElement = Nothing
If student.TryGetProperty("Grade", gradeElement) Then
sum += gradeElement.GetDouble()
Else
sum += 70
End If
count += 1
Next
End Using
Dim average As Double = sum / count
Console.WriteLine($"Average grade : {average}")
Powyższy kod ma następujące działanie:
- Przyjęto założenie, że kod JSON do analizy znajduje się w ciągu o nazwie
jsonString. - Oblicza średnią ocenę obiektów w
Studentstablicy, która maGradewłaściwość. - Przypisuje domyślną ocenę 70 dla uczniów, którzy nie mają klasy.
JsonDocumentTworzy wystąpienie w instrukcji,usingponieważJsonDocumentimplementujeIDisposableelement . Po usunięciuJsonDocumentwystąpienia utracisz również dostęp do wszystkich jegoJsonElementwystąpień. Aby zachować dostęp doJsonElementwystąpienia, utwórz jego kopię przed likwidacją wystąpienia nadrzędnegoJsonDocument. Aby utworzyć kopię, wywołaj metodę JsonElement.Clone. Aby uzyskać więcej informacji, zobacz JsonDocument is IDisposable.
Powyższy przykładowy kod zlicza uczniów, zwiększając zmienną count z każdą iterację. Alternatywą jest wywołanie metody GetArrayLength, jak pokazano w poniższym przykładzie:
double sum = 0;
int count = 0;
using (JsonDocument document = JsonDocument.Parse(jsonString))
{
JsonElement root = document.RootElement;
JsonElement studentsElement = root.GetProperty("Students");
count = studentsElement.GetArrayLength();
foreach (JsonElement student in studentsElement.EnumerateArray())
{
if (student.TryGetProperty("Grade", out JsonElement gradeElement))
{
sum += gradeElement.GetDouble();
}
else
{
sum += 70;
}
}
}
double average = sum / count;
Console.WriteLine($"Average grade : {average}");
Dim sum As Double = 0
Dim count As Integer = 0
Using document As JsonDocument = JsonDocument.Parse(jsonString)
Dim root As JsonElement = document.RootElement
Dim studentsElement As JsonElement = root.GetProperty("Students")
count = studentsElement.GetArrayLength()
For Each student As JsonElement In studentsElement.EnumerateArray()
Dim gradeElement As JsonElement = Nothing
If student.TryGetProperty("Grade", gradeElement) Then
sum += gradeElement.GetDouble()
Else
sum += 70
End If
Next
End Using
Dim average As Double = sum / count
Console.WriteLine($"Average grade : {average}")
Oto przykładowy kod JSON, który przetwarza ten kod:
{
"Class Name": "Science",
"Teacher\u0027s Name": "Jane",
"Semester": "2019-01-01",
"Students": [
{
"Name": "John",
"Grade": 94.3
},
{
"Name": "James",
"Grade": 81.0
},
{
"Name": "Julia",
"Grade": 91.9
},
{
"Name": "Jessica",
"Grade": 72.4
},
{
"Name": "Johnathan"
}
],
"Final": true
}
Podobny przykład użycia JsonNode zamiast elementu można znaleźć w przykładzieJsonDocument średniej klasy JsonNode.
Jak wyszukiwać elementy podrzędne JsonDocument i JsonElement
Wyszukiwania na JsonElement stronie wymagają sekwencyjnego wyszukiwania właściwości, dlatego są stosunkowo powolne (na przykład w przypadku używania metody TryGetProperty). System.Text.Json jest przeznaczony do zminimalizowania czasu analizy początkowej, a nie czasu wyszukiwania. W związku z tym użyj następujących metod, aby zoptymalizować wydajność podczas wyszukiwania JsonDocument obiektu:
- Użyj wbudowanych modułów wyliczających (EnumerateArray i EnumerateObject) zamiast wykonywać własne indeksowanie lub pętle.
- Nie należy wykonywać sekwencyjnego wyszukiwania całej
JsonDocumentza pośrednictwem każdej właściwości przy użyciu poleceniaRootElement. Zamiast tego wyszukaj zagnieżdżone obiekty JSON na podstawie znanej struktury danych JSON. Na przykład powyższe przykłady kodu szukają właściwości wStudentobiektach poprzez pętlęGradeprzezStudentobiekty i uzyskanie wartościGradedla każdego z nich, a nie wyszukiwanie wszystkichJsonElementobiektów, które szukająGradewłaściwości. Wykonanie tej drugiej czynności spowodowałoby niepotrzebne przekazywanie tych samych danych.
Używanie JsonDocument do zapisywania kodu JSON
W poniższym przykładzie pokazano, jak napisać kod JSON z elementu JsonDocument:
string jsonString = File.ReadAllText(inputFileName);
var writerOptions = new JsonWriterOptions
{
Indented = true
};
var documentOptions = new JsonDocumentOptions
{
CommentHandling = JsonCommentHandling.Skip
};
using FileStream fs = File.Create(outputFileName);
using var writer = new Utf8JsonWriter(fs, options: writerOptions);
using JsonDocument document = JsonDocument.Parse(jsonString, documentOptions);
JsonElement root = document.RootElement;
if (root.ValueKind == JsonValueKind.Object)
{
writer.WriteStartObject();
}
else
{
return;
}
foreach (JsonProperty property in root.EnumerateObject())
{
property.WriteTo(writer);
}
writer.WriteEndObject();
writer.Flush();
Dim jsonString As String = File.ReadAllText(inputFileName)
Dim writerOptions As JsonWriterOptions = New JsonWriterOptions With {
.Indented = True
}
Dim documentOptions As JsonDocumentOptions = New JsonDocumentOptions With {
.CommentHandling = JsonCommentHandling.Skip
}
Dim fs As FileStream = File.Create(outputFileName)
Dim writer As Utf8JsonWriter = New Utf8JsonWriter(fs, options:=writerOptions)
Dim document As JsonDocument = JsonDocument.Parse(jsonString, documentOptions)
Dim root As JsonElement = document.RootElement
If root.ValueKind = JsonValueKind.[Object] Then
writer.WriteStartObject()
Else
Return
End If
For Each [property] As JsonProperty In root.EnumerateObject()
[property].WriteTo(writer)
Next
writer.WriteEndObject()
writer.Flush()
Powyższy kod ma następujące działanie:
- Odczytuje plik JSON, ładuje dane do
JsonDocumentpliku i zapisuje formatowane (dość drukowane) dane JSON do pliku. - Umożliwia JsonDocumentOptions określenie, że komentarze w wejściowym formacie JSON są dozwolone, ale ignorowane.
- Po zakończeniu wywołaj Flush moduł zapisywania. Alternatywą jest pozwolić modułowi zapisywania automatycznie opróżnić, gdy jest on usuwany.
Oto przykład danych wejściowych JSON, które mają być przetwarzane przez przykładowy kod:
{"Class Name": "Science","Teacher's Name": "Jane","Semester": "2019-01-01","Students": [{"Name": "John","Grade": 94.3},{"Name": "James","Grade": 81.0},{"Name": "Julia","Grade": 91.9},{"Name": "Jessica","Grade": 72.4},{"Name": "Johnathan"}],"Final": true}
Wynikiem są następujące dość drukowane dane wyjściowe JSON:
{
"Class Name": "Science",
"Teacher\u0027s Name": "Jane",
"Semester": "2019-01-01",
"Students": [
{
"Name": "John",
"Grade": 94.3
},
{
"Name": "James",
"Grade": 81.0
},
{
"Name": "Julia",
"Grade": 91.9
},
{
"Name": "Jessica",
"Grade": 72.4
},
{
"Name": "Johnathan"
}
],
"Final": true
}
JsonDocument to IDisposable
JsonDocument tworzy widok danych w pamięci do buforu w puli. W związku z tym JsonDocument typ implementuje IDisposable i musi być używany wewnątrz using bloku.
Zwróć tylko element JsonDocument z interfejsu API, jeśli chcesz przenieść własność okresu istnienia i usunąć odpowiedzialność za obiekt wywołujący. W większości scenariuszy nie jest to konieczne. Jeśli obiekt wywołujący musi pracować z całym dokumentem JSON, zwróć CloneRootElementelement , który jest elementem JsonElement. Jeśli obiekt wywołujący musi pracować z określonym elementem w dokumencie JSON, zwróć Clone ten JsonElementelement . Jeśli zwrócisz RootElement element podrzędny lub bezpośrednio bez utworzenia Cloneelementu , obiekt wywołujący nie będzie mógł uzyskać dostępu do zwróconego JsonElement elementu po jego usunięciu JsonDocument .
Oto przykład, który wymaga utworzenia elementu Clone:
public JsonElement LookAndLoad(JsonElement source)
{
string json = File.ReadAllText(source.GetProperty("fileName").GetString());
using (JsonDocument doc = JsonDocument.Parse(json))
{
return doc.RootElement.Clone();
}
}
Powyższy kod oczekuje JsonElement właściwości , która zawiera fileName właściwość. Spowoduje to otwarcie pliku JSON i utworzenie pliku JsonDocument. Metoda zakłada, że obiekt wywołujący chce pracować z całym dokumentem, więc zwraca wartość CloneRootElement.
Jeśli otrzymasz element podrzędny JsonElement i zwrócisz element podrzędny, nie trzeba zwracać Clone elementu podrzędnego. Rozmówca jest odpowiedzialny za utrzymanie życia JsonDocument , do którego należy przekazany JsonElement . Na przykład:
public JsonElement ReturnFileName(JsonElement source)
{
return source.GetProperty("fileName");
}
JsonDocument Z JsonSerializerOptions
Za pomocą JsonSerializer polecenia można serializować i deserializować wystąpienie klasy JsonDocument. Jednak implementacja odczytu i zapisywania JsonDocument wystąpień przy użyciu JsonSerializer jest otoką nad elementami JsonDocument.ParseValue(Utf8JsonReader) i JsonDocument.WriteTo(Utf8JsonWriter). Ta otoka nie przekazuje żadnych ( JsonSerializerOptions funkcji serializatora) do Utf8JsonReader lub Utf8JsonWriter. Jeśli na przykład ustawisz wartość JsonSerializerOptions.DefaultIgnoreConditionWhenWritingNull i wywołasz JsonSerializer polecenie z przeciążeniem, które przyjmuje JsonSerializerOptionswartość , właściwości null nie zostaną zignorowane.
Poniższy przykład ilustruje wynik użycia metod, które przyjmują JsonSerializerOptions parametr i serializują JsonDocument wystąpienie:
using System.Text;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Text.Json.Serialization;
namespace JsonDocumentWithJsonSerializerOptions;
public class Program
{
public static void Main()
{
Person person = new Person { Name = "Nancy" };
// Default serialization - Address property included with null token.
// Output: {"Name":"Nancy","Address":null}
string personJsonWithNull = JsonSerializer.Serialize(person);
Console.WriteLine(personJsonWithNull);
// Serialize and ignore null properties - null Address property is omitted
// Output: {"Name":"Nancy"}
JsonSerializerOptions options = new()
{
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
};
string personJsonWithoutNull = JsonSerializer.Serialize(person, options);
Console.WriteLine(personJsonWithoutNull);
// Ignore null properties doesn't work when serializing JsonDocument instance
// by using JsonSerializer.
// Output: {"Name":"Nancy","Address":null}
var personJsonDocument = JsonSerializer.Deserialize<JsonDocument>(personJsonWithNull);
personJsonWithNull = JsonSerializer.Serialize(personJsonDocument, options);
Console.WriteLine(personJsonWithNull);
}
}
public class Person
{
public string? Name { get; set; }
public string? Address { get; set; }
}
Jeśli potrzebujesz funkcji JsonSerializerOptionsprogramu , użyj JsonSerializer z silnie typinymi elementami docelowymi (takimi jak Person klasa w tym przykładzie), a nie JsonDocument.
Korzystanie z polecenia Utf8JsonWriter
Utf8JsonWriter Jest to wysokowydajny sposób zapisu zakodowanego w formacie UTF-8 tekstu JSON z typowych typów platformy .NET, takich jak String, Int32i DateTime. Składnik zapisywania to typ niskiego poziomu, który może służyć do tworzenia niestandardowych serializatorów. Metoda JsonSerializer.Serialize używa Utf8JsonWriter pod okładkami.
W poniższym przykładzie pokazano, jak używać Utf8JsonWriter klasy:
var options = new JsonWriterOptions
{
Indented = true
};
using var stream = new MemoryStream();
using var writer = new Utf8JsonWriter(stream, options);
writer.WriteStartObject();
writer.WriteString("date", DateTimeOffset.UtcNow);
writer.WriteNumber("temp", 42);
writer.WriteEndObject();
writer.Flush();
string json = Encoding.UTF8.GetString(stream.ToArray());
Console.WriteLine(json);
Dim options As JsonWriterOptions = New JsonWriterOptions With {
.Indented = True
}
Dim stream As MemoryStream = New MemoryStream
Dim writer As Utf8JsonWriter = New Utf8JsonWriter(stream, options)
writer.WriteStartObject()
writer.WriteString("date", DateTimeOffset.UtcNow)
writer.WriteNumber("temp", 42)
writer.WriteEndObject()
writer.Flush()
Dim json As String = Encoding.UTF8.GetString(stream.ToArray())
Console.WriteLine(json)
Pisanie przy użyciu tekstu UTF-8
Aby uzyskać najlepszą możliwą wydajność podczas korzystania z Utf8JsonWriterelementu , zapis ładunków JSON jest już zakodowany jako tekst UTF-8, a nie jako ciągi UTF-16. Służy JsonEncodedText do buforowania i wstępnego kodowania znanych nazw właściwości ciągów i wartości jako statycznych oraz przekazywania ich do modułu zapisywania, a nie przy użyciu literałów ciągów UTF-16. Jest to szybsze niż buforowanie i używanie tablic bajtów UTF-8.
Takie podejście działa również w przypadku konieczności wykonania niestandardowej ucieczki. System.Text.Json nie pozwala wyłączyć ucieczki podczas pisania ciągu. Możesz jednak przekazać własny niestandardowy JavaScriptEncoder element jako opcję modułu zapisywania lub utworzyć własny JsonEncodedText , który używa JavascriptEncoder elementu do ucieczki, a następnie napisać wartość JsonEncodedText zamiast ciągu. Aby uzyskać więcej informacji, zobacz Dostosowywanie kodowania znaków.
Zapisywanie nieprzetworzonego kodu JSON
W niektórych scenariuszach możesz napisać "nieprzetworzone" dane JSON do ładunku JSON tworzonego za pomocą polecenia Utf8JsonWriter. Możesz to zrobić za pomocą Utf8JsonWriter.WriteRawValue polecenia . Oto typowe scenariusze:
Masz istniejący ładunek JSON, który chcesz ująć w nowy kod JSON.
Chcesz sformatować wartości inaczej niż domyślne
Utf8JsonWriterformatowanie.Na przykład możesz dostosować formatowanie liczb. Domyślnie System.Text.Json pomija punkt dziesiętny dla liczb całkowitych, zapisując
1zamiast1.0, na przykład . Uzasadnieniem jest to, że pisanie mniejszej liczby bajtów jest dobre dla wydajności. Załóżmy jednak, że użytkownik kodu JSON traktuje liczby z liczbami dziesiętnymi jako liczbami podwójnymi i liczbami bez liczby dziesiętnej jako liczby całkowite. Warto upewnić się, że liczby w tablicy są rozpoznawane jako podwójne, zapisując punkt dziesiętny i zero dla liczb całkowitych. W poniższym przykładzie pokazano, jak to zrobić:using System.Text; using System.Text.Json; namespace WriteRawJson; public class Program { public static void Main() { JsonWriterOptions writerOptions = new() { Indented = true, }; using MemoryStream stream = new(); using Utf8JsonWriter writer = new(stream, writerOptions); writer.WriteStartObject(); writer.WriteStartArray("defaultJsonFormatting"); foreach (double number in new double[] { 50.4, 51 }) { writer.WriteStartObject(); writer.WritePropertyName("value"); writer.WriteNumberValue(number); writer.WriteEndObject(); } writer.WriteEndArray(); writer.WriteStartArray("customJsonFormatting"); foreach (double result in new double[] { 50.4, 51 }) { writer.WriteStartObject(); writer.WritePropertyName("value"); writer.WriteRawValue( FormatNumberValue(result), skipInputValidation: true); writer.WriteEndObject(); } writer.WriteEndArray(); writer.WriteEndObject(); writer.Flush(); string json = Encoding.UTF8.GetString(stream.ToArray()); Console.WriteLine(json); } static string FormatNumberValue(double numberValue) { return numberValue == Convert.ToInt32(numberValue) ? numberValue.ToString() + ".0" : numberValue.ToString(); } } // output: //{ // "defaultJsonFormatting": [ // { // "value": 50.4 // }, // { // "value": 51 // } // ], // "customJsonFormatting": [ // { // "value": 50.4 // }, // { // "value": 51.0 // } // ] //}
Dostosowywanie ucieczki znaków
Ustawienie StringEscapeHandling oferuje JsonTextWriter opcje ucieczki wszystkich znaków innych niż ASCII lub znaków HTML. Domyślnie Utf8JsonWriter unika wszystkich znaków innych niż ASCII i HTML. Ta ucieczka jest wykonywana ze względów bezpieczeństwa w głębi systemu obrony. Aby określić inne zasady ucieczki, utwórz JavaScriptEncoder element i ustaw .JsonWriterOptions.Encoder Aby uzyskać więcej informacji, zobacz Dostosowywanie kodowania znaków.
Zapisywanie wartości null
Aby zapisać wartości null przy użyciu metody , Utf8JsonWriterwywołaj metodę :
- WriteNull aby zapisać parę klucz-wartość z wartością null jako wartość.
- WriteNullValue w celu zapisania wartości null jako elementu tablicy JSON.
W przypadku właściwości ciągu, jeśli ciąg ma wartość null, WriteString i WriteStringValue są równoważne WriteNull wartościom i WriteNullValue.
Zapisywanie wartości przedziału czasu, identyfikatora URI lub znaku
Aby napisać Timespanwartości , Urilub char , sformatuj je jako ciągi (na przykład przez wywołanie ToString()metody , i wywołaj metodę WriteStringValue.
Korzystanie z polecenia Utf8JsonReader
Utf8JsonReader to wysokowydajny, niski alokacja, czytnik tylko do przodu dla tekstu JSON zakodowanego w formacie UTF-8, odczytywany z elementu ReadOnlySpan<byte> lub ReadOnlySequence<byte>. Jest Utf8JsonReader to typ niskiego poziomu, który może służyć do tworzenia niestandardowych parserów i deserializatorów. Metoda JsonSerializer.Deserialize używa Utf8JsonReader pod okładkami. Utf8JsonReader Nie można ich używać bezpośrednio z Visual Basic kodu. Aby uzyskać więcej informacji, zobacz Visual Basic pomocy technicznej.
W poniższym przykładzie pokazano, jak używać Utf8JsonReader klasy:
var options = new JsonReaderOptions
{
AllowTrailingCommas = true,
CommentHandling = JsonCommentHandling.Skip
};
var reader = new Utf8JsonReader(jsonUtf8Bytes, options);
while (reader.Read())
{
Console.Write(reader.TokenType);
switch (reader.TokenType)
{
case JsonTokenType.PropertyName:
case JsonTokenType.String:
{
string? text = reader.GetString();
Console.Write(" ");
Console.Write(text);
break;
}
case JsonTokenType.Number:
{
int intValue = reader.GetInt32();
Console.Write(" ");
Console.Write(intValue);
break;
}
// Other token types elided for brevity
}
Console.WriteLine();
}
' This code example doesn't apply to Visual Basic. For more information, go to the following URL:
' https://docs.microsoft.com/dotnet/standard/serialization/system-text-json-how-to#visual-basic-support
Powyższy kod zakłada, że jsonUtf8 zmienna jest tablicą bajtów zawierającą prawidłowy kod JSON zakodowany jako UTF-8.
Filtrowanie danych przy użyciu Utf8JsonReader
W poniższym przykładzie pokazano, jak synchronicznie odczytać plik i wyszukać wartość.
using System.Text;
using System.Text.Json;
namespace SystemTextJsonSamples
{
public class Utf8ReaderFromFile
{
private static readonly byte[] s_nameUtf8 = Encoding.UTF8.GetBytes("name");
private static ReadOnlySpan<byte> Utf8Bom => new byte[] { 0xEF, 0xBB, 0xBF };
public static void Run()
{
// ReadAllBytes if the file encoding is UTF-8:
string fileName = "UniversitiesUtf8.json";
ReadOnlySpan<byte> jsonReadOnlySpan = File.ReadAllBytes(fileName);
// Read past the UTF-8 BOM bytes if a BOM exists.
if (jsonReadOnlySpan.StartsWith(Utf8Bom))
{
jsonReadOnlySpan = jsonReadOnlySpan.Slice(Utf8Bom.Length);
}
// Or read as UTF-16 and transcode to UTF-8 to convert to a ReadOnlySpan<byte>
//string fileName = "Universities.json";
//string jsonString = File.ReadAllText(fileName);
//ReadOnlySpan<byte> jsonReadOnlySpan = Encoding.UTF8.GetBytes(jsonString);
int count = 0;
int total = 0;
var reader = new Utf8JsonReader(jsonReadOnlySpan);
while (reader.Read())
{
JsonTokenType tokenType = reader.TokenType;
switch (tokenType)
{
case JsonTokenType.StartObject:
total++;
break;
case JsonTokenType.PropertyName:
if (reader.ValueTextEquals(s_nameUtf8))
{
// Assume valid JSON, known schema
reader.Read();
if (reader.GetString()!.EndsWith("University"))
{
count++;
}
}
break;
}
}
Console.WriteLine($"{count} out of {total} have names that end with 'University'");
}
}
}
' This code example doesn't apply to Visual Basic. For more information, go to the following URL:
' https://docs.microsoft.com/dotnet/standard/serialization/system-text-json-how-to#visual-basic-support
Aby uzyskać asynchroniczną wersję tego przykładu, zobacz projekt JSON przykładów dla platformy .NET.
Powyższy kod ma następujące działanie:
Przyjęto założenie, że kod JSON zawiera tablicę obiektów, a każdy obiekt może zawierać właściwość "name" ciągu typu.
Zlicza obiekty i wartości właściwości "name", które kończą się ciągiem "University".
Zakłada się, że plik jest zakodowany jako UTF-16 i transkoduje go w formacie UTF-8. Plik zakodowany jako UTF-8 można odczytać bezpośrednio do obiektu
ReadOnlySpan<byte>przy użyciu następującego kodu:ReadOnlySpan<byte> jsonReadOnlySpan = File.ReadAllBytes(fileName);Jeśli plik zawiera znak kolejności bajtów UTF-8 (BOM), usuń go przed przekazaniem bajtów do
Utf8JsonReaderelementu , ponieważ czytelnik oczekuje tekstu. W przeciwnym razie BOM jest uważany za nieprawidłowy kod JSON, a czytelnik zgłasza wyjątek.
Oto przykład JSON, który można odczytać z poprzedniego kodu. Wynikowy komunikat podsumowujący to "2 na 4 mają nazwy kończące się ciągiem "University":
[
{
"web_pages": [ "https://contoso.edu/" ],
"alpha_two_code": "US",
"state-province": null,
"country": "United States",
"domains": [ "contoso.edu" ],
"name": "Contoso Community College"
},
{
"web_pages": [ "http://fabrikam.edu/" ],
"alpha_two_code": "US",
"state-province": null,
"country": "United States",
"domains": [ "fabrikam.edu" ],
"name": "Fabrikam Community College"
},
{
"web_pages": [ "http://www.contosouniversity.edu/" ],
"alpha_two_code": "US",
"state-province": null,
"country": "United States",
"domains": [ "contosouniversity.edu" ],
"name": "Contoso University"
},
{
"web_pages": [ "http://www.fabrikamuniversity.edu/" ],
"alpha_two_code": "US",
"state-province": null,
"country": "United States",
"domains": [ "fabrikamuniversity.edu" ],
"name": "Fabrikam University"
}
]
Odczytywanie ze strumienia przy użyciu Utf8JsonReader
Podczas odczytywania dużego pliku (na przykład gigabajta lub więcej rozmiaru) warto uniknąć konieczności załadowania całego pliku do pamięci jednocześnie. W tym scenariuszu można użyć elementu FileStream.
W przypadku używania elementu Utf8JsonReader do odczytu ze strumienia obowiązują następujące reguły:
- Bufor zawierający częściowy ładunek JSON musi być co najmniej tak duży, jak największy token JSON w nim, aby czytelnik mógł kontynuować postęp.
- Bufor musi być co najmniej tak duży, jak największa sekwencja białych znaków w formacie JSON.
- Czytelnik nie śledzi danych, które odczytuje, dopóki nie zostanie całkowicie odczytany w TokenType ładunku JSON. Więc gdy w buforze są bajty pozostawione, trzeba je ponownie przekazać do czytnika. Możesz użyć BytesConsumed polecenia , aby określić, ile bajtów pozostało.
Poniższy kod ilustruje sposób odczytywania ze strumienia. W przykładzie przedstawiono element MemoryStream. Podobny kod będzie działać z elementem FileStream, z wyjątkiem sytuacji, gdy FileStream element zawiera kod UTF-8 BOM na początku. W takim przypadku należy usunąć te trzy bajty z buforu przed przekazaniem pozostałych bajtów do .Utf8JsonReader W przeciwnym razie czytelnik zgłosi wyjątek, ponieważ BOM nie jest traktowana jako prawidłowa część kodu JSON.
Przykładowy kod rozpoczyna się od buforu 4 KB i podwaja rozmiar buforu za każdym razem, gdy stwierdza, że rozmiar nie jest wystarczająco duży, aby zmieścić pełny token JSON, który jest wymagany dla czytelnika, aby kontynuować postęp w ładunku JSON. Przykład JSON podany w fragmencie kodu wyzwala wzrost rozmiaru buforu tylko wtedy, gdy ustawisz bardzo mały rozmiar buforu początkowego, na przykład 10 bajtów. W przypadku ustawienia początkowego rozmiaru buforu na 10 Console.WriteLine instrukcje ilustrują przyczynę i wpływ rozmiaru buforu. Przy początkowym rozmiarze buforu 4 KB cały przykładowy kod JSON jest wyświetlany przez poszczególne Console.WriteLineelementy , a rozmiar buforu nigdy nie musi być zwiększany.
using System.Text;
using System.Text.Json;
namespace SystemTextJsonSamples
{
public class Utf8ReaderPartialRead
{
public static void Run()
{
var jsonString = @"{
""Date"": ""2019-08-01T00:00:00-07:00"",
""Temperature"": 25,
""TemperatureRanges"": {
""Cold"": { ""High"": 20, ""Low"": -10 },
""Hot"": { ""High"": 60, ""Low"": 20 }
},
""Summary"": ""Hot"",
}";
byte[] bytes = Encoding.UTF8.GetBytes(jsonString);
var stream = new MemoryStream(bytes);
var buffer = new byte[4096];
// Fill the buffer.
// For this snippet, we're assuming the stream is open and has data.
// If it might be closed or empty, check if the return value is 0.
stream.Read(buffer);
// We set isFinalBlock to false since we expect more data in a subsequent read from the stream.
var reader = new Utf8JsonReader(buffer, isFinalBlock: false, state: default);
Console.WriteLine($"String in buffer is: {Encoding.UTF8.GetString(buffer)}");
// Search for "Summary" property name
while (reader.TokenType != JsonTokenType.PropertyName || !reader.ValueTextEquals("Summary"))
{
if (!reader.Read())
{
// Not enough of the JSON is in the buffer to complete a read.
GetMoreBytesFromStream(stream, ref buffer, ref reader);
}
}
// Found the "Summary" property name.
Console.WriteLine($"String in buffer is: {Encoding.UTF8.GetString(buffer)}");
while (!reader.Read())
{
// Not enough of the JSON is in the buffer to complete a read.
GetMoreBytesFromStream(stream, ref buffer, ref reader);
}
// Display value of Summary property, that is, "Hot".
Console.WriteLine($"Got property value: {reader.GetString()}");
}
private static void GetMoreBytesFromStream(
MemoryStream stream, ref byte[] buffer, ref Utf8JsonReader reader)
{
int bytesRead;
if (reader.BytesConsumed < buffer.Length)
{
ReadOnlySpan<byte> leftover = buffer.AsSpan((int)reader.BytesConsumed);
if (leftover.Length == buffer.Length)
{
Array.Resize(ref buffer, buffer.Length * 2);
Console.WriteLine($"Increased buffer size to {buffer.Length}");
}
leftover.CopyTo(buffer);
bytesRead = stream.Read(buffer.AsSpan(leftover.Length));
}
else
{
bytesRead = stream.Read(buffer);
}
Console.WriteLine($"String in buffer is: {Encoding.UTF8.GetString(buffer)}");
reader = new Utf8JsonReader(buffer, isFinalBlock: bytesRead == 0, reader.CurrentState);
}
}
}
' This code example doesn't apply to Visual Basic. For more information, go to the following URL:
' https://docs.microsoft.com/dotnet/standard/serialization/system-text-json-how-to#visual-basic-support
W poprzednim przykładzie nie określono limitu wielkości buforu. Jeśli rozmiar tokenu jest zbyt duży, kod może zakończyć się niepowodzeniem OutOfMemoryException z wyjątkiem. Może się tak zdarzyć, jeśli kod JSON zawiera token o rozmiarze około 1 GB lub więcej, ponieważ podwojenie rozmiaru 1 GB powoduje, że rozmiar jest zbyt duży, aby zmieścić się w buforze int32 .
Utf8JsonReader to struktura ref
Utf8JsonReader Ponieważ typ jest strukturą ref, ma pewne ograniczenia. Nie można na przykład przechowywać go jako pola w klasie lub strukturach innych niż struktura ref. Aby osiągnąć wysoką wydajność, ten typ musi byćref struct, ponieważ musi buforować dane wejściowe ReadOnlySpanbyte<>, która sama jest strukturą ref. Ponadto ten typ jest modyfikowalny, ponieważ przechowuje stan. W związku z tym należy przekazać go przez odwołanie , a nie przez wartość. Przekazanie go według wartości spowoduje skopiowanie struktury, a zmiany stanu nie będą widoczne dla elementu wywołującego. Aby uzyskać więcej informacji na temat używania struktur ref, zobacz Pisanie bezpiecznego i wydajnego kodu w języku C#.
Odczytywanie tekstu UTF-8
Aby uzyskać najlepszą możliwą wydajność podczas korzystania z Utf8JsonReaderelementu , odczyt ładunków JSON jest już zakodowany jako tekst UTF-8, a nie jako ciągi UTF-16. Aby zapoznać się z przykładem kodu, zobacz Filtrowanie danych przy użyciu elementu Utf8JsonReader.
Odczyt z wieloma segmentami ReadOnlySequence
Jeśli dane wejściowe JSON są elementem ReadOnlySpanbyte<>, każdy element JSON można uzyskać dostęp z ValueSpan właściwości czytnika podczas przechodzenia przez pętlę odczytu. Jeśli jednak dane wejściowe są wartością ReadOnlySequencebyte<> (co jest wynikiem odczytu z elementu ), PipeReaderniektóre elementy JSON mogą zaciemniać wiele segmentów ReadOnlySequence<byte> obiektu. Te elementy nie będą dostępne z ValueSpan ciągłego bloku pamięci. Zamiast tego za każdym razem, gdy masz wiele segmentów ReadOnlySequence<byte> jako dane wejściowe, sonduj HasValueSequence właściwość na czytniku, aby dowiedzieć się, jak uzyskać dostęp do bieżącego elementu JSON. Oto zalecany wzorzec:
while (reader.Read())
{
switch (reader.TokenType)
{
// ...
ReadOnlySpan<byte> jsonElement = reader.HasValueSequence ?
reader.ValueSequence.ToArray() :
reader.ValueSpan;
// ...
}
}
Użyj wartościTextEquals dla odnośników nazw właściwości
Nie używaj ValueSpan funkcji do porównywania bajtów bajtów przez wywołanie SequenceEqual odnośników nazw właściwości. Wywołaj ValueTextEquals metodę , ponieważ ta metoda usuwa wszystkie znaki, które są ucieczki w formacie JSON. Oto przykład pokazujący sposób wyszukiwania właściwości o nazwie "name":
private static readonly byte[] s_nameUtf8 = Encoding.UTF8.GetBytes("name");
while (reader.Read())
{
switch (reader.TokenType)
{
case JsonTokenType.StartObject:
total++;
break;
case JsonTokenType.PropertyName:
if (reader.ValueTextEquals(s_nameUtf8))
{
count++;
}
break;
}
}
Odczytywanie wartości null do typów wartości dopuszczalnych do wartości null
Wbudowane System.Text.Json interfejsy API zwracają tylko typy wartości innych niż null. Na przykład Utf8JsonReader.GetBoolean zwraca wartość bool. Zgłasza wyjątek w przypadku znalezienia Null go w formacie JSON. W poniższych przykładach pokazano dwa sposoby obsługi wartości null: jeden przez zwrócenie typu wartości dopuszczającej wartość null i jeden przez zwrócenie wartości domyślnej:
public bool? ReadAsNullableBoolean()
{
_reader.Read();
if (_reader.TokenType == JsonTokenType.Null)
{
return null;
}
if (_reader.TokenType != JsonTokenType.True && _reader.TokenType != JsonTokenType.False)
{
throw new JsonException();
}
return _reader.GetBoolean();
}
public bool ReadAsBoolean(bool defaultValue)
{
_reader.Read();
if (_reader.TokenType == JsonTokenType.Null)
{
return defaultValue;
}
if (_reader.TokenType != JsonTokenType.True && _reader.TokenType != JsonTokenType.False)
{
throw new JsonException();
}
return _reader.GetBoolean();
}
Zobacz też
- System.Text.Json Przegląd
- Tworzenie wystąpień JsonSerializerOptions
- Włączanie dopasowywania bez uwzględniania wielkości liter
- Dostosowywanie nazw i wartości właściwości
- Ignorowanie właściwości
- Zezwalanie na nieprawidłowy kod JSON
- Obsługa przepełnienia kodu JSON lub używanie elementu JsonElement lub JsonNode
- Zachowywanie odwołań i obsługa odwołań cykli
- Deserializacji do niezmiennych typów i niepubliczne metody dostępu
- Serializacja polimorficzna
- Migrowanie z Newtonsoft.Json do System.Text.Json
- Dostosowywanie kodowania znaków
- Używanie elementów DOM, Utf8JsonReader i Utf8JsonWriter
- Pisanie niestandardowych konwerterów na potrzeby serializacji JSON
- Obsługa elementów DateTime i DateTimeOffset
- Jak używać generowania źródła
- Obsługiwane typy kolekcji
- System.Text.Json Dokumentacja interfejsu API
- System.Text.Json. Dokumentacja interfejsu API serializacji