Como usar um modelo de objeto de documento JSON em System.Text.Json
Este artigo mostra como usar um modelo de objeto de documento JSON (DOM) para acesso aleatório a dados em uma carga JSON útil.
Opções de JSON DOM
Trabalhar com um DOM é uma alternativa à desserialização com JsonSerializer quando:
- Você não tem um tipo para desserializar.
- O JSON que você recebe não tem um esquema fixo e deve ser inspecionado para saber o que ele contém.
System.Text.Json
fornece duas maneiras de criar um DOM JSON:
JsonDocument fornece a capacidade de criar um DOM somente leitura usando
Utf8JsonReader
o . Os elementos JSON que compõem a carga útil podem ser acessados através do JsonElement tipo. OJsonElement
tipo fornece enumeradores de matriz e objeto junto com APIs para converter texto JSON em tipos .NET comuns.JsonDocument
expõe uma RootElement propriedade. Para obter mais informações, consulte Usar JsonDocument mais adiante neste artigo.JsonNode e as classes que derivam dele no System.Text.Json.Nodes namespace fornecem a capacidade de criar um DOM mutável. Os elementos JSON que compõem a carga útil podem ser acessados por meio dos JsonNodetipos , JsonObject, JsonArray, JsonValue, e JsonElement . Para obter mais informações, consulte Usar
JsonNode
mais adiante neste artigo.
Considere os seguintes fatores ao escolher entre JsonDocument
e JsonNode
:
- O
JsonNode
DOM pode ser alterado após a sua criação. OJsonDocument
DOM é imutável. - O
JsonDocument
DOM fornece acesso mais rápido aos seus dados.
Utilizar o comando JsonNode
O exemplo a seguir mostra como usar JsonNode e os outros tipos no System.Text.Json.Nodes namespace para:
- Criar um DOM a partir de uma cadeia de caracteres JSON
- Escreva JSON a partir de um DOM.
- Obtenha um valor, objeto ou matriz de um 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"
}
}
Crie um DOM JsonNode com inicializadores de objeto e faça alterações
O exemplo a seguir mostra como:
- Crie um DOM usando inicializadores de objeto.
- Faça alterações em um 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
// }
// }
//}
}
}
Desserializar subseções de uma carga JSON
O exemplo a seguir mostra como usar JsonNode para navegar até uma subseção de uma árvore JSON e desserializar um único valor, um tipo personalizado ou uma matriz dessa subseção.
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
}
}
Exemplo de nota média de JsonNode
O exemplo a seguir seleciona uma matriz JSON que tem valores inteiros e calcula um valor médio:
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
O código anterior:
- Calcula uma nota média para objetos em uma
Students
matriz que têm umaGrade
propriedade. - Atribui uma nota padrão de 70 para alunos que não têm nota.
- Obtém o número de alunos da
Count
propriedade deJsonArray
.
JsonNode
com JsonSerializerOptions
Você pode usar JsonSerializer
para serializar e desserializar uma instância do JsonNode
. No entanto, se você usar uma sobrecarga que leva JsonSerializerOptions
, a instância de opções é usada apenas para obter conversores personalizados. Outros recursos da instância de opções não são usados. Por exemplo, se você definir JsonSerializerOptions.DefaultIgnoreCondition como WhenWritingNull e chamar JsonSerializer
com uma sobrecarga que leva JsonSerializerOptions
, as propriedades nulas não serão ignoradas.
A mesma limitação se aplica aos JsonNode
métodos que tomam um JsonSerializerOptions
parâmetro: WriteTo(Utf8JsonWriter, JsonSerializerOptions) e ToJsonString(JsonSerializerOptions). Essas APIs usam JsonSerializerOptions
apenas para obter conversores personalizados.
O exemplo a seguir ilustra o resultado do uso de métodos que usam um JsonSerializerOptions
parâmetro e serializam uma JsonNode
instância:
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; }
}
Se você precisar de recursos diferentes de conversores personalizados, use JsonSerializer
com destinos fortemente tipados (como a Person
classe neste exemplo) em vez de JsonNode
JsonSerializerOptions
.
Manipular a ordem da propriedade
JsonObject é um dos elementos na carga útil de um JsonNode, e representa um objeto JSON mutável. Embora o tipo seja modelado como um IDictionary<string, JsonNode>
, onde cada entrada é uma propriedade do objeto, ele encapsula uma ordem de propriedade implícita. No entanto, APIs como Insert(Int32, String, JsonNode) e RemoveAt(Int32) efetivamente modelam o tipo como um dicionário ordenado, permitindo que você insira e remova itens em um índice específico. Essas APIs permitem modificações em instâncias de objeto que podem influenciar diretamente a ordem da propriedade.
O código a seguir mostra um exemplo de adição ou movimentação de uma propriedade específica para o início do objeto.
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;
}
Comparar JsonNodes
Para comparar dois JsonNode
objetos para igualdade, incluindo seus elementos descendentes, use o JsonNode.DeepEquals(JsonNode, JsonNode) método.
Utilizar o comando JsonDocument
O exemplo a seguir mostra como usar a JsonDocument classe para acesso aleatório a dados em uma cadeia de caracteres 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}")
O código anterior:
- Assume que o JSON a ser analisado está em uma cadeia de caracteres chamada
jsonString
. - Calcula uma nota média para objetos em uma
Students
matriz que têm umaGrade
propriedade. - Atribui uma nota padrão de 70 para alunos que não têm nota.
- Cria a
JsonDocument
instância em umausing
instrução porqueJsonDocument
implementaIDisposable
. Depois que umaJsonDocument
instância é descartada, você também perde o acesso a todas as instânciasJsonElement
. Para manter o acesso a umaJsonElement
instância, faça uma cópia dela antes que a instância paiJsonDocument
seja descartada. Para fazer uma cópia, ligue JsonElement.Clonepara . Para obter mais informações, consulte JsonDocument is IDisposable.
O código de exemplo anterior conta os alunos incrementando uma count
variável a cada iteração. Uma alternativa é chamar GetArrayLength, como mostrado no exemplo a seguir:
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}")
Aqui está um exemplo do JSON que esse código processa:
{
"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
}
Para obter um exemplo semelhante que usa JsonNode
em vez de , consulte Exemplo de nota média do JsonDocument
JsonNode.
Como pesquisar subelementos JsonDocument e JsonElement
As pesquisas exigem JsonElement
uma pesquisa sequencial das propriedades e, portanto, são relativamente lentas (por exemplo, ao usar TryGetProperty
). System.Text.Json foi projetado para minimizar o tempo de análise inicial em vez do tempo de pesquisa. Portanto, use as seguintes abordagens para otimizar o desempenho ao pesquisar um JsonDocument
objeto:
- Use os enumeradores internos (EnumerateArray e EnumerateObject) em vez de fazer sua própria indexação ou loops.
- Não faça uma pesquisa sequencial em todos
JsonDocument
os imóveis usandoRootElement
o . Em vez disso, pesquise em objetos JSON aninhados com base na estrutura conhecida dos dados JSON. Por exemplo, os exemplos de código anteriores procuram umaGrade
propriedade emStudent
objetos fazendo looping pelosStudent
objetos e obtendo o valor de para cada um, em vez deGrade
pesquisar todos osJsonElement
objetos procurandoGrade
propriedades. Fazer isso resultaria em repasses desnecessários sobre os mesmos dados.
Comparar JsonElements
Para comparar dois JsonElement
objetos para igualdade, incluindo seus elementos descendentes, use o JsonElement.DeepEquals(JsonElement, JsonElement) método.
JsonElement left = JsonDocument.Parse("10e-3").RootElement;
JsonElement right = JsonDocument.Parse("0.01").RootElement;
bool equal = JsonElement.DeepEquals(left, right);
Console.WriteLine(equal); // True.
Use JsonDocument
para escrever JSON
O exemplo a seguir mostra como escrever JSON a partir de um 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()
O código anterior:
- Lê um arquivo JSON, carrega os dados em um
JsonDocument
e grava JSON formatado (bem impresso) em um arquivo. - Usa JsonDocumentOptions para especificar que os comentários no JSON de entrada são permitidos, mas ignorados.
- Quando terminar, chama Flush o escritor. Uma alternativa é deixar o gravador lavar automaticamente quando estiver descartado.
Aqui está um exemplo de entrada JSON a ser processada pelo código de exemplo:
{"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}
O resultado é a seguinte saída JSON impressa com elegância:
{
"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 é IDisposable
JsonDocument
Cria uma exibição na memória dos dados em um buffer em pool. Portanto, o JsonDocument
tipo implementa e precisa ser usado dentro de IDisposable
um using
bloco.
Só devolva um JsonDocument
da sua API se quiser transferir a propriedade vitalícia e descartar a responsabilidade para o chamador. Na maioria dos cenários, isso não é necessário. Se o chamador precisar trabalhar com todo o documento JSON, retorne o Clone RootElementdo , que é um JsonElementarquivo . Se o chamador precisar trabalhar com um elemento específico dentro do documento JSON, retorne o Clone .JsonElement Se você retornar o RootElement
ou um subelemento diretamente sem fazer um Clone
, o chamador não poderá acessar o devolvido JsonElement
depois que o JsonDocument
que o possui for descartado.
Aqui está um exemplo que requer que você faça um Clone
:
public JsonElement LookAndLoad(JsonElement source)
{
string json = File.ReadAllText(source.GetProperty("fileName").GetString());
using (JsonDocument doc = JsonDocument.Parse(json))
{
return doc.RootElement.Clone();
}
}
O código anterior espera um JsonElement
que contém uma fileName
propriedade. Ele abre o arquivo JSON e cria um JsonDocument
arquivo . O método pressupõe que o chamador deseja trabalhar com o documento inteiro, portanto, ele retorna o Clone
do RootElement
.
Se você receber um JsonElement
e estiver retornando um subelemento, não será necessário retornar um Clone
dos subelementos. O interlocutor é responsável por manter vivo aquele JsonDocument
a que pertence o passageiro JsonElement
. Por exemplo:
public JsonElement ReturnFileName(JsonElement source)
{
return source.GetProperty("fileName");
}
JsonDocument
com JsonSerializerOptions
Você pode usar JsonSerializer
para serializar e desserializar uma instância do JsonDocument
. No entanto, a implementação para instâncias de leitura e gravação JsonDocument
usando JsonSerializer
é um wrapper sobre o JsonDocument.ParseValue(Utf8JsonReader) e JsonDocument.WriteTo(Utf8JsonWriter). Este wrapper não encaminha nenhum JsonSerializerOptions
(recursos do serializador) para Utf8JsonReader
ou Utf8JsonWriter
. Por exemplo, se você definir JsonSerializerOptions.DefaultIgnoreCondition como WhenWritingNull e chamar JsonSerializer
com uma sobrecarga que leva JsonSerializerOptions
, as propriedades nulas não serão ignoradas.
O exemplo a seguir ilustra o resultado do uso de métodos que usam um JsonSerializerOptions
parâmetro e serializam uma JsonDocument
instância:
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; }
}
Se você precisar de recursos do , use JsonSerializer
com destinos fortemente tipados (como a Person
classe neste exemplo) em vez de JsonDocument
JsonSerializerOptions
.