如何處理溢位 JSON 或使用 JsonElement 或 JsonNode
本文說明如何使用 System.Text.Json 命名空間來處理溢位 JSON。 其也會示範如何還原序列化為 JsonElement 或 JsonNode,以作為目標類型可能不完全符合所有要還原序列化之 JSON 的替代方案。
處理溢位 JSON
還原序列化時,您可能會在 JSON 中接收不是以目標類型屬性表示的資料。 例如,假設您的目標類型如下:
public class WeatherForecast
{
public DateTimeOffset Date { get; set; }
public int TemperatureCelsius { get; set; }
public string? Summary { get; set; }
}
Public Class WeatherForecast
Public Property [Date] As DateTimeOffset
Public Property TemperatureCelsius As Integer
Public Property Summary As String
End Class
而要還原序列化的 JSON 如下:
{
"Date": "2019-08-01T00:00:00-07:00",
"temperatureCelsius": 25,
"Summary": "Hot",
"DatesAvailable": [
"2019-08-01T00:00:00-07:00",
"2019-08-02T00:00:00-07:00"
],
"SummaryWords": [
"Cool",
"Windy",
"Humid"
]
}
如果您將顯示的 JSON 還原序列化為所顯示類型,則 DatesAvailable
和 SummaryWords
屬性會無處可去,且會遺失。 若要擷取如這些屬性的額外資料,請將 [JsonExtensionData] 屬性 (attribute) 套用至類型為 Dictionary<string,object>
或 Dictionary<string,JsonElement>
的屬性 (property):
public class WeatherForecastWithExtensionData
{
public DateTimeOffset Date { get; set; }
public int TemperatureCelsius { get; set; }
public string? Summary { get; set; }
[JsonExtensionData]
public Dictionary<string, JsonElement>? ExtensionData { get; set; }
}
Public Class WeatherForecastWithExtensionData
Public Property [Date] As DateTimeOffset
Public Property TemperatureCelsius As Integer
Public Property Summary As String
<JsonExtensionData>
Public Property ExtensionData As Dictionary(Of String, Object)
End Class
下表顯示將稍早所顯示 JSON 還原序列化為此範例類型的結果。 額外的資料會變成 ExtensionData
屬性的機碼值組:
屬性 | 值 | 備註 |
---|---|---|
Date |
"8/1/2019 12:00:00 AM -07:00" |
|
TemperatureCelsius |
0 |
因為區分大小寫不相符 (JSON 中的 temperatureCelsius ),所以不會設定屬性。 |
Summary |
"Hot" |
|
ExtensionData |
"temperatureCelsius": 25, "DatesAvailable": ["2019-08-01T00:00:00-07:00","2019-08-02T00:00:00-07:00"], "SummaryWords": ["Cool","Windy","Humid"] |
因為大小寫不相符,所以 temperatureCelsius 是多餘的,且會變成字典中的機碼值組。 JSON 中的每個額外陣列都會變成機碼值組,並將陣列當作值物件。 |
序列化目標物件時,延伸模組資料機碼值組會變成 JSON 屬性,就如它們位於傳入 JSON 時一樣:
{
"Date": "2019-08-01T00:00:00-07:00",
"TemperatureCelsius": 0,
"Summary": "Hot",
"temperatureCelsius": 25,
"DatesAvailable": [
"2019-08-01T00:00:00-07:00",
"2019-08-02T00:00:00-07:00"
],
"SummaryWords": [
"Cool",
"Windy",
"Humid"
]
}
請注意,ExtensionData
屬性名稱不會出現在 JSON 中。 此行為可讓 JSON 進行來回行程,而不會遺失任何不會還原序列化的額外資料。
下列範例顯示從 JSON 到還原序列化物件,並返回 JSON 的來回行程:
using System.Text.Json;
using System.Text.Json.Serialization;
namespace RoundtripExtensionData
{
public class WeatherForecast
{
public DateTimeOffset Date { get; set; }
public int TemperatureCelsius { get; set; }
public string? Summary { get; set; }
[JsonExtensionData]
public Dictionary<string, JsonElement>? ExtensionData { get; set; }
}
public class Program
{
public static void Main()
{
string jsonString =
@"{
""Date"": ""2019-08-01T00:00:00-07:00"",
""temperatureCelsius"": 25,
""Summary"": ""Hot"",
""SummaryField"": ""Hot"",
""DatesAvailable"": [
""2019-08-01T00:00:00-07:00"",
""2019-08-02T00:00:00-07:00""
],
""SummaryWords"": [
""Cool"",
""Windy"",
""Humid""
]
}";
WeatherForecast weatherForecast =
JsonSerializer.Deserialize<WeatherForecast>(jsonString)!;
var serializeOptions = new JsonSerializerOptions { WriteIndented = true };
jsonString = JsonSerializer.Serialize(weatherForecast, serializeOptions);
Console.WriteLine($"JSON output:\n{jsonString}\n");
}
}
}
// output:
//JSON output:
//{
// "Date": "2019-08-01T00:00:00-07:00",
// "TemperatureCelsius": 0,
// "Summary": "Hot",
// "temperatureCelsius": 25,
// "SummaryField": "Hot",
// "DatesAvailable": [
// "2019-08-01T00:00:00-07:00",
// "2019-08-02T00:00:00-07:00"
// ],
// "SummaryWords": [
// "Cool",
// "Windy",
// "Humid"
// ]
//}
還原序列化為 JsonElement 或 JsonNode
如果您只想要靈活地決定特定屬性可接受的 JSON,替代方式是還原序列化為 JsonElement 或 JsonNode。 任何有效的 JSON 屬性都可以還原序列化為 JsonElement
或 JsonNode
。 選擇 JsonElement
建立 不可變 的物件,或 JsonNode
建立 可變 物件。
下列範例示範類別的 JSON 來回行程,其中包含 JsonElement
和 JsonNode
類型的屬性。
using System.Text.Json;
using System.Text.Json.Nodes;
namespace RoundtripJsonElementAndNode
{
public class WeatherForecast
{
public DateTimeOffset Date { get; set; }
public int TemperatureCelsius { get; set; }
public string? Summary { get; set; }
public JsonElement DatesAvailable { get; set; }
public JsonNode? SummaryWords { get; set; }
}
public class Program
{
public static void Main()
{
string jsonString =
@"{
""Date"": ""2019-08-01T00:00:00-07:00"",
""TemperatureCelsius"": 25,
""Summary"": ""Hot"",
""DatesAvailable"": [
""2019-08-01T00:00:00-07:00"",
""2019-08-02T00:00:00-07:00""
],
""SummaryWords"": [
""Cool"",
""Windy"",
""Humid""
]
}";
WeatherForecast? weatherForecast =
JsonSerializer.Deserialize<WeatherForecast>(jsonString);
var serializeOptions = new JsonSerializerOptions { WriteIndented = true };
jsonString = JsonSerializer.Serialize(weatherForecast, serializeOptions);
Console.WriteLine(jsonString);
}
}
}
// output:
//{
// "Date": "2019-08-01T00:00:00-07:00",
// "TemperatureCelsius": 25,
// "Summary": "Hot",
// "DatesAvailable": [
// "2019-08-01T00:00:00-07:00",
// "2019-08-02T00:00:00-07:00"
// ],
// "SummaryWords": [
// "Cool",
// "Windy",
// "Humid"
// ]
//}