如何在 System.Text.Json 中使用 JSON 文件物件模型
本文說明如何使用 JSON 文件物件模型 (DOM) 來隨機存取 JSON 承載中的資料。
JSON DOM 選項
使用 DOM 是利用 JsonSerializer 還原序列化替代方法的情境:
- 您沒有要還原序列化的類型。
- 您收到的 JSON 沒有固定結構描述,必須加以檢查才能知道其所包含的內容時。
System.Text.Json
提供兩種方式來建置 JSON DOM:
JsonDocument 提供使用
Utf8JsonReader
建置唯讀 DOM 的功能。 撰寫承載的 JSON 元素可以透過 JsonElement 類型存取。JsonElement
類型提供陣列和物件列舉程式,以及將 JSON 文字轉換為一般.NET 類型的 API。JsonDocument
會公開 RootElement 屬性。 如需詳細資訊,請參閱本文件稍後的使用 JsonDocument。JsonNode 和在 System.Text.Json.Nodes 命名空間中自其衍生的類別,提供建立可變 DOM 的功能。 撰寫承載的 JSON 項目可以透過 JsonNode、JsonObject、JsonArray、JsonValue 和 JsonElement 類型存取。 如需詳細資訊,請參閱本文稍後的使用
JsonNode
。
在 JsonDocument
和 JsonNode
之間選擇時,請考慮下列因素:
JsonNode
DOM 可以在建立之後變更。JsonDocument
DOM 是不可變的。JsonDocument
DOM 可讓您更快速地存取其資料。
使用 JsonNode
下列範例示範如何使用 JsonNode 和 System.Text.Json.Nodes 命名空間中的其他類型:
- 從 JSON 字串建立 DOM
- 從 DOM 撰寫 JSON。
- 從 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"
}
}
使用物件初始設定式建立 JsonNode DOM 並進行變更
下列範例顯示如何:
- 使用物件初始設定式建立 DOM。
- 對 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
// }
// }
//}
}
}
還原序列化 JSON 承載的子區段
下列範例示範如何使用 JsonNode 瀏覽至 JSON 樹狀結構的子區段,並從該子區段還原序列化單一值、自訂類型或陣列。
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
}
}
JsonNode 平均成績範例
下列範例會選取具有整數值的 JSON 陣列,並計算平均值:
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
上述 程式碼:
- 計算具有
Grade
屬性之Students
陣列中物件的平均成績。 - 為沒有分數的學生指派預設的 70 分成績。
- 從
JsonArray
的Count
屬性取得學生數目。
包含 JsonSerializerOptions
的 JsonNode
您可以使用 JsonSerializer
來序列化和還原序列化 JsonNode
的執行個體。 不過,如果您使用採用 JsonSerializerOptions
的多載,則選項執行個體只會用來取得自訂轉換器。 系統不會使用選項執行個體的其他功能。 例如,如果您將 JsonSerializerOptions.DefaultIgnoreCondition 設定為 WhenWritingNull,並使用採用 JsonSerializerOptions
的多載呼叫 JsonSerializer
,則不會忽略 null 屬性。
相同的限制適用於採用 JsonSerializerOptions
參數的 JsonNode
方法:WriteTo(Utf8JsonWriter, JsonSerializerOptions) 和 ToJsonString(JsonSerializerOptions)。 這些 API 只會使用 JsonSerializerOptions
來取得自訂轉換器。
下列範例說明使用採用 JsonSerializerOptions
參數並序列化 JsonNode
執行個體的方法結果:
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; }
}
如果您需要自訂轉換器以外的 JsonSerializerOptions
功能,請使用 JsonSerializer
搭配強型別目標 (例如此範例中的 Person
類別) 而非 JsonNode
。
操作屬性順序
JsonObject 是 承載中的其中一個專案 JsonNode,它代表可變動的 JSON 物件。 即使型別會模型化為 IDictionary<string, JsonNode>
,其中每個專案都是 對象的屬性,但它會封裝隱含的屬性順序。 不過,可讓您在特定索引插入和移除專案,例如 Insert(Int32, String, JsonNode) 並 RemoveAt(Int32) 有效地將類型模型化為已排序的字典。 這些 API 允許修改可直接影響屬性順序的物件實例。
下列程式代碼示範將特定屬性加入或移動至 物件的開頭的範例。
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;
}
比較 JsonNodes
若要比較兩個 JsonNode
物件是否相等,包括其子代元素,請使用 JsonNode.DeepEquals(JsonNode, JsonNode) 方法。
使用 JsonDocument
下列範例示範如何使用 JsonDocument 類別來隨機存取 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}")
上述 程式碼:
- 假設要分析的 JSON 位於名為
jsonString
的字串中。 - 計算具有
Grade
屬性之Students
陣列中物件的平均成績。 - 為沒有分數的學生指派預設的 70 分成績。
- 因為
JsonDocument
會實作IDisposable
,所以請在using
陳述式中建立JsonDocument
執行個體。 處置JsonDocument
執行個體之後,您也會失去其所有JsonElement
執行個體的存取權。 若要保留JsonElement
執行個體的存取權,請在處置父JsonDocument
執行個體之前,先建立其複本。 若要建立複本,請呼叫 JsonElement.Clone。 如需詳細資訊,請參閱 JsonDocument 為 IDisposable。
上述範例程式碼會藉由遞增每個反覆項目的 count
變數來計算學生。 替代方法是呼叫 GetArrayLength,如下列範例所示:
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}")
下列是此程式碼所處理 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
}
如需使用 JsonNode
而非 JsonDocument
的類似範例,請參閱 JsonNode 平均成績範例。
如何搜尋 JsonDocument 與 JsonElement 以尋找子元素
因為 JsonElement
搜尋需要循序搜尋屬性,所以相對緩慢 (例如使用 TryGetProperty
時)。 System.Text.Json 的設計目的是將初始剖析時間降至最低,而不是查閱時間。 因此,在搜尋 JsonDocument
物件時,請使用下列方法來最佳化效能:
- 使用內建列舉程式 (EnumerateArray 和 EnumerateObject),而非執行您自己的索引或迴圈。
- 請勿透過使用
RootElement
在整個JsonDocument
上循序搜尋每個屬性。 相反地,請根據 JSON 資料的已知結構來搜尋巢狀 JSON 物件。 例如,上述程式碼範例會藉由在Student
物件之間執行迴圈並取得每個物件的Grade
值來尋找Student
物件中的Grade
屬性,而非搜尋所有JsonElement
物件來尋找Grade
屬性。 執行後者會導致不必要地傳遞相同的資料。
比較 JsonElements
若要比較兩個 JsonElement
物件是否相等,包括其子代元素,請使用 JsonElement.DeepEquals(JsonElement, JsonElement) 方法。
JsonElement left = JsonDocument.Parse("10e-3").RootElement;
JsonElement right = JsonDocument.Parse("0.01").RootElement;
bool equal = JsonElement.DeepEquals(left, right);
Console.WriteLine(equal); // True.
使用 JsonDocument
來撰寫 JSON
下列範例示範如何從 JsonDocument 撰寫 JSON:
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()
上述 程式碼:
- 讀取 JSON 檔案、將資料載入至
JsonDocument
,並將格式化的 (已調整格式) JSON 寫入檔案。 - 使用 JsonDocumentOptions 來指定輸入 JSON 中允許但會被忽略的註解。
- 完成時,在寫入器上呼叫 Flush。 替代方法是讓寫入器在受到處置時自動排清。
下列是範例程式碼所要處理的 JSON 輸入範例:
{"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}
結果是下列已調整格式的 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 為 IDisposable
JsonDocument
會將資料的記憶體內部檢視建置到集區緩衝區中。 因此,JsonDocument
類型會實作 IDisposable
,且必須在 using
區塊內使用。
只有在您想要移轉存留期擁有權並處置呼叫端的責任時,才會從您的 API 傳回 JsonDocument
。 在大部分情況下,這並非必要。 如果呼叫端需要使用整個 JSON 文件,則會傳回 RootElement 的 Clone,也就是 JsonElement。 如果呼叫端需要使用 JSON 文件內的特定元素,則會傳回該 JsonElement 的 Clone。 如果您直接傳回 RootElement
或子元素,而非發出 Clone
,則呼叫端將無法在處置擁有傳回項目的 JsonDocument
之後,存取其傳回的 JsonElement
。
下列是要求您發出 Clone
的範例:
public JsonElement LookAndLoad(JsonElement source)
{
string json = File.ReadAllText(source.GetProperty("fileName").GetString());
using (JsonDocument doc = JsonDocument.Parse(json))
{
return doc.RootElement.Clone();
}
}
上述程式碼預期包含 fileName
屬性的 JsonElement
。 其會開啟 JSON 檔案並建立 JsonDocument
。 因為該方法假設呼叫端想要使用整個文件,所以會傳回 RootElement
的 Clone
。
如果您收到 JsonElement
並傳回子元素,則不需要傳回子元素的 Clone
。 呼叫端負責讓傳入 JsonElement
所屬的 JsonDocument
保持運作。 例如:
public JsonElement ReturnFileName(JsonElement source)
{
return source.GetProperty("fileName");
}
包含 JsonSerializerOptions
的 JsonDocument
您可以使用 JsonSerializer
來序列化和還原序列化 JsonDocument
的執行個體。 不過,使用 JsonSerializer
來讀取和寫入 JsonDocument
執行個體的實作是 JsonDocument.ParseValue(Utf8JsonReader) 和 JsonDocument.WriteTo(Utf8JsonWriter) 的包裝函式。 此包裝函式不會將任何 JsonSerializerOptions
(序列化程式功能) 轉接至 Utf8JsonReader
或 Utf8JsonWriter
。 例如,如果您將 JsonSerializerOptions.DefaultIgnoreCondition 設定為 WhenWritingNull,並使用採用 JsonSerializerOptions
的多載呼叫 JsonSerializer
,則不會忽略 null 屬性。
下列範例說明使用採用 JsonSerializerOptions
參數並序列化 JsonDocument
執行個體的方法結果:
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; }
}
如果您需要 JsonSerializerOptions
的功能,請使用 JsonSerializer
搭配強型別目標 (例如此範例中的 Person
類別) 而非 JsonDocument
。