Så här använder du en JSON-dokumentobjektmodell i System.Text.Json

Den här artikeln visar hur du använder en JSON-dokumentobjektmodell (DOM) för slumpmässig åtkomst till data i en JSON-nyttolast.

JSON DOM-val

Att arbeta med en DOM är ett alternativ till deserialisering med JsonSerializer när:

  • Du har ingen typ att deserialisera till.
  • JSON-filen som du får har inget fast schema och måste inspekteras för att veta vad den innehåller.

System.Text.Json innehåller två sätt att skapa en JSON DOM:

Tänk på följande faktorer när du väljer mellan JsonDocument och JsonNode:

  • DOM JsonNode kan ändras när den har skapats. DOM JsonDocument är oföränderlig.
  • JsonDocument DOM ger snabbare åtkomst till sina data.

Använda JsonNode

I följande exempel visas hur du använder JsonNode och de andra typerna System.Text.Json.Nodes i namnområdet till:

  • Skapa en DOM från en JSON-sträng
  • Skriv JSON från en DOM.
  • Hämta ett värde, ett objekt eller en matris från en 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"
    }
}

Skapa en JsonNode DOM med objektinitierare och gör ändringar

I följande exempel visas hur du:

  • Skapa en DOM med hjälp av objektinitierare.
  • Gör ändringar i en 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
        //    }
        //  }
        //}
    }
}

Deserialisera underavsnitt för en JSON-nyttolast

I följande exempel visas hur du använder JsonNode för att navigera till ett underavsnitt av ett JSON-träd och deserialisera ett enda värde, en anpassad typ eller en matris från den underavsnittet.

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
    }
}

Exempel på JsonNode-genomsnittsbetyg

I följande exempel väljs en JSON-matris som har heltalsvärden och beräknar ett genomsnittligt värde:

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

Koden ovan:

  • Beräknar ett genomsnittsbetyg för objekt i en Students matris som har en Grade egenskap.
  • Tilldelar ett standardbetyg på 70 för elever som inte har ett betyg.
  • Hämtar antalet studenter från Count egenskapen JsonArray.

JsonNode med JsonSerializerOptions

Du kan använda JsonSerializer för att serialisera och deserialisera en instans av JsonNode. Men om du använder en överlagring som tar JsonSerializerOptionsanvänds alternativinstansen endast för att hämta anpassade konverterare. Andra funktioner i alternativinstansen används inte. Om du till exempel ställer in JsonSerializerOptions.DefaultIgnoreConditionWhenWritingNull och anropar JsonSerializer med en överlagring som tar JsonSerializerOptionsignoreras inte null-egenskaper.

Samma begränsning gäller för de JsonNode metoder som använder en JsonSerializerOptions parameter: WriteTo(Utf8JsonWriter, JsonSerializerOptions) och ToJsonString(JsonSerializerOptions). Dessa API:er används JsonSerializerOptions endast för att hämta anpassade konverterare.

I följande exempel visas resultatet av att använda metoder som tar en JsonSerializerOptions parameter och serialiserar en JsonNode instans:

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; }
}

Om du behöver andra funktioner JsonSerializerOptions än anpassade konverterare använder JsonSerializer du med starkt skrivna mål (till exempel Person klassen i det här exemplet) i stället JsonNodeför .

Ändra egenskapsordning

JsonObject är ett av elementen i nyttolasten för ett JsonNode, och det representerar ett föränderligt JSON-objekt. Även om typen modelleras som en IDictionary<string, JsonNode>, där varje post är en egenskap för objektet, kapslar den in en implicit egenskapsordning. API:er som Insert(Int32, String, JsonNode) och RemoveAt(Int32) modellerar effektivt typen som en ordnad ordlista genom att låta dig infoga och ta bort objekt i ett specifikt index. Dessa API:er tillåter ändringar i objektinstanser som direkt kan påverka egenskapsordningen.

Följande kod visar ett exempel på hur du lägger till eller flyttar en specifik egenskap till början av objektet.

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;
}

Jämför JsonNodes

Om du vill jämföra två JsonNode objekt för likhet, inklusive deras underordnade element, använder du JsonNode.DeepEquals(JsonNode, JsonNode) metoden.

Använda JsonDocument

I följande exempel visas hur du använder JsonDocument klassen för slumpmässig åtkomst till data i en JSON-sträng:

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}")

Koden ovan:

  • Förutsätter att JSON som ska analyseras finns i en sträng med namnet jsonString.
  • Beräknar ett genomsnittsbetyg för objekt i en Students matris som har en Grade egenskap.
  • Tilldelar ett standardbetyg på 70 för elever som inte har ett betyg.
  • Skapar instansen JsonDocument i enusing -instruktion eftersom JsonDocument implementerar IDisposable. När en JsonDocument instans har avyttrats förlorar du även åtkomsten till alla dess JsonElement instanser. Om du vill behålla åtkomsten till en JsonElement instans gör du en kopia av den innan den överordnade JsonDocument instansen tas bort. Om du vill göra en kopia anropar du JsonElement.Clone. Mer information finns i JsonDocument is IDisposable (JsonDocument is IDisposable).

Föregående exempelkod räknar eleverna genom att öka en count variabel med varje iteration. Ett alternativ är att anropa GetArrayLength, enligt följande exempel:

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}")

Här är ett exempel på JSON som den här koden bearbetar:

{
  "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
}

Ett liknande exempel som använder JsonNode i stället för JsonDocumentfinns i JsonNode average grade example (Genomsnittligt betygsexempel för JsonNode).

Så här söker du efter underelement i JsonDocument och JsonElement

Sökningar på JsonElement kräver en sekventiell sökning av egenskaperna och är därför relativt långsamma (till exempel när du använder TryGetProperty). System.Text.Json är utformad för att minimera den inledande parsningstiden i stället för uppslagstiden. Använd därför följande metoder för att optimera prestanda vid sökning via ett JsonDocument objekt:

  • Använd inbyggda uppräknare (EnumerateArray och EnumerateObject) i stället för att göra egna indexering eller loopar.
  • Gör inte en sekventiell sökning på det hela taget JsonDocument genom varje egenskap med hjälp RootElementav . Sök i stället efter kapslade JSON-objekt baserat på den kända strukturen för JSON-data. Till exempel letar de föregående kodexemplen efter en Grade egenskap i Student objekt genom att loopa igenom objekten Student och hämta värdet Grade för var och en, i stället för att söka igenom alla JsonElement objekt som söker Grade efter egenskaper. Om du gör det senare skulle det leda till onödiga passeringar över samma data.

Jämför JsonElements

Om du vill jämföra två JsonElement objekt för likhet, inklusive deras underordnade element, använder du JsonElement.DeepEquals(JsonElement, JsonElement) metoden.

JsonElement left = JsonDocument.Parse("10e-3").RootElement;
JsonElement right = JsonDocument.Parse("0.01").RootElement;
bool equal = JsonElement.DeepEquals(left, right);
Console.WriteLine(equal); // True.

Använd JsonDocument för att skriva JSON

I följande exempel visas hur du skriver JSON från en 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()

Koden ovan:

  • Läser en JSON-fil, läser in data i en JsonDocument, och skriver formaterad (ganska utskriven) JSON till en fil.
  • Används JsonDocumentOptions för att ange att kommentarer i JSON-indata tillåts men ignoreras.
  • När du är klar anropar Flush du författaren. Ett alternativ är att låta skrivaren rensa automatiskt när den tas bort.

Här är ett exempel på JSON-indata som ska bearbetas av exempelkoden:

{"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}

Resultatet är följande ganska utskrivna JSON-utdata:

{
  "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 är IDisposable

JsonDocument skapar en minnesintern vy över data till en poolbuffert. JsonDocument Därför implementerar IDisposable och måste typen användas i ett using block.

Returnera endast en JsonDocument från ditt API om du vill överföra livstidsägarskap och ta ansvar för anroparen. I de flesta scenarier är det inte nödvändigt. Om anroparen behöver arbeta med hela JSON-dokumentet returnerar du Clone för RootElement, som är en JsonElement. Om anroparen behöver arbeta med ett visst element i JSON-dokumentet returnerar Clone du den JsonElement. Om du returnerar RootElement eller ett underelement direkt utan att göra ett Clonekan anroparen inte komma åt det returnerade JsonElement efter JsonDocument att det som äger det har avyttrats.

Här är ett exempel som kräver att du gör en Clone:

public JsonElement LookAndLoad(JsonElement source)
{
    string json = File.ReadAllText(source.GetProperty("fileName").GetString());

    using (JsonDocument doc = JsonDocument.Parse(json))
    {
        return doc.RootElement.Clone();
    }
}

Föregående kod förväntar sig en JsonElement som innehåller en fileName egenskap. Den öppnar JSON-filen och skapar en JsonDocument. Metoden förutsätter att anroparen vill arbeta med hela dokumentet, så den returnerar Clone för RootElement.

Om du får ett JsonElement och returnerar ett underelement är det inte nödvändigt att returnera ett Clone av delelementet. Uppringaren ansvarar för att hålla liv i den JsonDocument som den införda JsonElement tillhör. Till exempel:

public JsonElement ReturnFileName(JsonElement source)
{
   return source.GetProperty("fileName");
}

JsonDocument med JsonSerializerOptions

Du kan använda JsonSerializer för att serialisera och deserialisera en instans av JsonDocument. Implementeringen för att läsa och skriva JsonDocument instanser med hjälp JsonSerializer av är dock en omslutning över JsonDocument.ParseValue(Utf8JsonReader) och JsonDocument.WriteTo(Utf8JsonWriter). Den här omslutningen vidarebefordrar inte några JsonSerializerOptions (serialiserarfunktioner) till Utf8JsonReader eller Utf8JsonWriter. Om du till exempel ställer in JsonSerializerOptions.DefaultIgnoreConditionWhenWritingNull och anropar JsonSerializer med en överlagring som tar JsonSerializerOptionsignoreras inte null-egenskaper.

I följande exempel visas resultatet av att använda metoder som tar en JsonSerializerOptions parameter och serialiserar en JsonDocument instans:

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; }
}

Om du behöver funktioner JsonSerializerOptionsi använder JsonSerializer du med starkt skrivna mål (till exempel Person klassen i det här exemplet) i stället JsonDocumentför .

Se även