Jak używać modelu obiektu dokumentu JSON w programie System.Text.Json
W tym artykule pokazano, jak używać modelu obiektów dokumentów JSON (DOM) do losowego dostępu do danych w ładunku JSON.
Opcje modelu DOM w formacie JSON
Praca z dom jest alternatywą dla deserializacji w JsonSerializer przypadku:
- Nie masz typu do deserializacji.
- Otrzymany kod JSON nie ma stałego schematu i musi być sprawdzany, 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 . TypJsonElement
udostępnia moduły wyliczania tablic i obiektów wraz z interfejsami API w celu konwertowania tekstu JSON na typowe typy platformy .NET.JsonDocument
uwidacznia RootElement właściwość. Aby uzyskać więcej informacji, zobacz Używanie narzędzia JsonDocument w dalszej części tego artykułu.JsonNode i klasy, które pochodzą z niego w System.Text.Json.Nodes przestrzeni nazw, zapewniają możliwość tworzenia modyfikowalnego 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
JsonNode
w dalszej części tego artykułu.
Podczas wybierania między elementami JsonDocument
i JsonNode
należy wziąć pod uwagę następujące czynniki:
- Dom
JsonNode
można zmienić po jego utworzeniu. DomJsonDocument
jest niezmienny. - Dom
JsonDocument
zapewnia szybszy dostęp do danych.
Korzystanie z polecenia JsonNode
W poniższym przykładzie pokazano, jak używać JsonNode i innych typów w przestrzeni nazw do System.Text.Json.Nodes :
- Tworzenie modelu DOM na podstawie ciągu JSON
- Zapis 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 elementu DOM JsonNode z inicjatorami 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ą narzędzia 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;
JsonNode document = JsonNode.Parse(jsonString)!;
JsonNode root = document.Root;
JsonArray studentsArray = root["Students"]!.AsArray();
int 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ę dla obiektów w
Students
tablicy, która maGrade
właściwość. - Przypisuje domyślną ocenę 70 dla uczniów, którzy nie mają klasy.
- Pobiera liczbę uczniów z
Count
właściwościJsonArray
.
JsonNode
z JsonSerializerOptions
Można użyć JsonSerializer
do serializacji i deserializacji wystąpienia klasy JsonNode
. Jeśli jednak 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 zostanie ustawiona JsonSerializerOptions.DefaultIgnoreCondition WhenWritingNull wartość i wywołana JsonSerializer
z przeciążeniem, które przyjmuje JsonSerializerOptions
, 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() { 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}
JsonNode? 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 z JsonSerializer
silnie typinymi obiektami docelowymi (takimi jak Person
klasa w tym przykładzie), a nie JsonNode
.
Manipulowanie kolejnością właściwości
JsonObject jest jednym z elementów w ładunku elementu JsonNode, który reprezentuje modyfikowalny obiekt JSON. Mimo że typ jest modelowany jako IDictionary<string, JsonNode>
element , gdzie każdy wpis jest właściwością obiektu, hermetyzuje niejawną kolejność właściwości. Jednak interfejsy API, takie jak Insert(Int32, String, JsonNode) i RemoveAt(Int32) skutecznie modeluje typ jako uporządkowany słownik, umożliwiając wstawianie i usuwanie elementów w określonym indeksie. Te interfejsy API umożliwiają modyfikacje wystąpień obiektów, które mogą mieć bezpośredni wpływ na kolejność właściwości.
Poniższy kod przedstawia przykład dodawania lub przenoszenia określonej właściwości na początek obiektu.
var schema = (JsonObject)JsonSerializerOptions.Default.GetJsonSchemaAsNode(typeof(MyPoco));
JsonNode? idValue;
switch (schema.IndexOf("$id"))
{
// $id property missing.
case < 0:
idValue = (JsonNode)"https://example.com/schema";
schema.Insert(0, "$id", idValue);
break;
// $id property already at the start of the object.
case 0:
break;
// $id exists but not at the start of the object.
case int index:
idValue = schema[index];
schema.RemoveAt(index);
schema.Insert(0, "$id", idValue);
break;
}
Porównanie węzłów JsonNodes
Aby porównać dwa JsonNode
obiekty pod kątem równości, w tym ich elementy potomne, użyj JsonNode.DeepEquals(JsonNode, JsonNode) metody .
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ę dla obiektów w
Students
tablicy, która maGrade
właściwość. - Przypisuje domyślną ocenę 70 dla uczniów, którzy nie mają klasy.
JsonDocument
Tworzy wystąpienie w instrukcjiusing
, ponieważJsonDocument
implementujeIDisposable
element . Po usunięciuJsonDocument
wystąpienia utracisz również dostęp do wszystkich jegoJsonElement
wystąpień. Aby zachować dostęp doJsonElement
wystą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 (Dokument JsonDocument to 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ład kodu 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
}
Aby zapoznać się z podobnym przykładem, który używa JsonNode
zamiast elementu , zobacz przykład średniej JsonDocument
klasy JsonNode.
Jak wyszukiwać elementy podrzędne JsonDocument i JsonElement
JsonElement
Wyszukiwanie wymaga sekwencyjnego wyszukiwania właściwości i dlatego jest stosunkowo powolne (na przykład w przypadku używania metody TryGetProperty
). System.Text.Json program został zaprojektowany tak, aby zminimalizować czas analizy początkowej, a nie czas wyszukiwania. W związku z tym należy użyć następujących metod optymalizacji wydajności 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 dla całej
JsonDocument
całej właściwości za pomocą metodyRootElement
. Zamiast tego wyszukaj zagnieżdżone obiekty JSON na podstawie znanej struktury danych JSON. Na przykład powyższe przykłady kodu wyszukująGrade
właściwość wStudent
obiektach, tworząc pętlę przezStudent
obiekty i uzyskując wartośćGrade
dla każdego z nich, zamiast przeszukiwać wszystkieJsonElement
obiekty wyszukująceGrade
właściwości. Wykonanie tych ostatnich spowoduje niepotrzebne przekazanie tych samych danych.
Porównanie elementów JsonElements
Aby porównać dwa JsonElement
obiekty pod kątem równości, w tym ich elementy potomne, użyj JsonElement.DeepEquals(JsonElement, JsonElement) metody .
JsonElement left = JsonDocument.Parse("10e-3").RootElement;
JsonElement right = JsonDocument.Parse("0.01").RootElement;
bool equal = JsonElement.DeepEquals(left, right);
Console.WriteLine(equal); // True.
Użyj JsonDocument
polecenia , aby zapisać kod JSON
W poniższym przykładzie pokazano, jak napisać kod JSON z pliku 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
JsonDocument
pliku 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łania Flush modułu zapisywania. Alternatywą jest pozwolić modułowi zapisywania na automatyczne opróżnienie, gdy zostanie usunięte.
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}
Wynik jest następującymi dość drukowanymi danymi wyjściowymi 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 w buforze w puli. W związku z tym JsonDocument
typ implementuje IDisposable
i musi być używany wewnątrz using
bloku.
Zwróć JsonDocument
element z interfejsu API tylko wtedy, gdy 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óć element Clone RootElement, czyli JsonElement. Jeśli obiekt wywołujący musi pracować z określonym elementem w dokumencie JSON, zwróć Clone ten JsonElementelement . Jeśli zwracasz element podrzędny RootElement
lub bezpośrednio bez tworzenia Clone
elementu , obiekt wywołujący nie będzie mógł uzyskać dostępu do zwróconego JsonElement
elementu po usunięciu elementu będącego JsonDocument
właścicielem.
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ść Clone
.RootElement
Jeśli otrzymasz element JsonElement
i zwraca element podrzędny, nie jest konieczne zwrócenie elementu Clone
podrzędnego. Wywołujący jest odpowiedzialny za utrzymanie przy życiu JsonDocument
, do którego należy przekazany JsonElement
element. Na przykład:
public JsonElement ReturnFileName(JsonElement source)
{
return source.GetProperty("fileName");
}
JsonDocument
z JsonSerializerOptions
Można użyć JsonSerializer
do serializacji i deserializacji wystąpienia klasy JsonDocument
. Jednak implementacja odczytywania i zapisywania JsonDocument
wystąpień przy JsonSerializer
użyciu jest otoką obiektów JsonDocument.ParseValue(Utf8JsonReader) i JsonDocument.WriteTo(Utf8JsonWriter). Ta otoka nie przekazuje żadnych JsonSerializerOptions
(funkcji serializatora) do Utf8JsonReader
lub Utf8JsonWriter
. Jeśli na przykład zostanie ustawiona JsonSerializerOptions.DefaultIgnoreCondition WhenWritingNull wartość i wywołana JsonSerializer
z przeciążeniem, które przyjmuje JsonSerializerOptions
, 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.Json;
using System.Text.Json.Serialization;
namespace JsonDocumentWithJsonSerializerOptions;
public class Program
{
public static void Main()
{
Person person = new() { 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}
JsonDocument? 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 JsonSerializerOptions
, należy używać JsonSerializer
z silnie typinymi obiektami docelowymi (takimi jak Person
klasa w tym przykładzie) zamiast JsonDocument
.