4 回答

TA貢獻1844條經驗 獲得超8個贊
在 .NET 6 中,添加了擴展方法以直接從orJsonSerializer
反序列化對象:JsonElement
JsonDocument
public static partial class JsonSerializer
{
? ? public static TValue? Deserialize<TValue>(this JsonDocument document, JsonSerializerOptions? options = null);
? ? public static object? Deserialize(this JsonDocument document, Type returnType, JsonSerializerOptions? options = null);
? ? public static TValue? Deserialize<TValue>(this JsonDocument document, JsonTypeInfo<TValue> jsonTypeInfo);
? ? public static object? Deserialize(this JsonDocument document, Type returnType, JsonSerializerContext context);
? ? public static TValue? Deserialize<TValue>(this JsonElement element, JsonSerializerOptions? options = null);
? ? public static object? Deserialize(this JsonElement element, Type returnType, JsonSerializerOptions? options = null);
? ? public static TValue? Deserialize<TValue>(this JsonElement element, JsonTypeInfo<TValue> jsonTypeInfo);
? ? public static object? Deserialize(this JsonElement element, Type returnType, JsonSerializerContext context);
}
現在您將能夠執行以下操作:
using var jDoc = JsonDocument.Parse(str);
var myClass = jDoc.RootElement.GetProperty("SomeProperty").Deserialize<SomeClass>();
筆記:
JsonDocument
是一次性的。根據文檔,該類利用池化內存中的資源...未能正確處置該對象將導致內存未返回到池中,這將增加GC框架各個部分的因此,請務必用聲明來聲明您的
jDoc
情況using
。新方法應該出現在.NET 6.0 Preview RC1中。
它們是為了響應增強請求而添加的。我們應該能夠從 DOM #31274 進行序列化和序列化,該請求已關閉。
還為新的可變 JSON 文檔節點添加了類似的擴展方法
JsonNode
public static TValue? Deserialize<TValue>(this JsonNode? node, JsonSerializerOptions? options = null)
public static object? Deserialize(this JsonNode? node, Type returnType, JsonSerializerOptions? options = null)
public static TValue? Deserialize<TValue>(this JsonNode? node, JsonTypeInfo<TValue> jsonTypeInfo)
public static object? Deserialize(this JsonNode? node, Type returnType, JsonSerializerContext context)
在 .NET 5 及更早版本中,這些方法不存在。作為解決方法,您可以通過寫入中間byte緩沖區而不是字符串來獲得更好的性能,因為 和JsonDocument都Utf8JsonReader直接使用byte跨度而不是字符串或char跨度。如文檔中所述:
序列化為 UTF-8 比使用基于字符串的方法大約快 5-10%。區別在于字節(UTF-8)不需要轉換為字符串(UTF-16)。
public static partial class JsonExtensions
{
? ? public static T ToObject<T>(this JsonElement element, JsonSerializerOptions options = null)
? ? {
? ? ? ? var bufferWriter = new ArrayBufferWriter<byte>();
? ? ? ? using (var writer = new Utf8JsonWriter(bufferWriter))
? ? ? ? ? ? element.WriteTo(writer);
? ? ? ? return JsonSerializer.Deserialize<T>(bufferWriter.WrittenSpan, options);
? ? }
? ? public static T ToObject<T>(this JsonDocument document, JsonSerializerOptions options = null)
? ? {
? ? ? ? if (document == null)
? ? ? ? ? ? throw new ArgumentNullException(nameof(document));
? ? ? ? return document.RootElement.ToObject<T>(options);
? ? }
}
演示小提琴在這里。

TA貢獻1783條經驗 獲得超4個贊
我遇到了同樣的問題,所以我編寫了一些擴展方法,目前效果很好。如果他們將其作為內置方法提供以避免對字符串的額外分配,那就太好了。
public static T ToObject<T>(this JsonElement element)
{
var json = element.GetRawText();
return JsonSerializer.Deserialize<T>(json);
}
public static T ToObject<T>(this JsonDocument document)
{
var json = document.RootElement.GetRawText();
return JsonSerializer.Deserialize<T>(json);
}
然后使用如下:
jDoc.RootElement.GetProperty("SomeProperty").ToObject<SomeClass>();

TA貢獻1909條經驗 獲得超7個贊
只是包括允許您通過 指定返回類型的方法Type returnType
。
public static partial class JsonExtensions
{
? ? public static T ToObject<T>(this JsonElement element, JsonSerializerOptions options = null)
? ? {
? ? ? ? var bufferWriter = new ArrayBufferWriter<byte>();
? ? ? ? using (var writer = new Utf8JsonWriter(bufferWriter))
? ? ? ? {
? ? ? ? ? ? element.WriteTo(writer);
? ? ? ? }
? ? ? ? return JsonSerializer.Deserialize<T>(bufferWriter.WrittenSpan, options);
? ? }
? ? public static T ToObject<T>(this JsonDocument document, JsonSerializerOptions options = null)
? ? {
? ? ? ? if (document == null)
? ? ? ? {
? ? ? ? ? ? throw new ArgumentNullException(nameof(document));
? ? ? ? }
? ? ? ? return document.RootElement.ToObject<T>(options);
? ? }? ? ? ?
? ? public static object ToObject(this JsonElement element, Type returnType, JsonSerializerOptions options = null)
? ? {
? ? ? ? var bufferWriter = new ArrayBufferWriter<byte>();
? ? ? ? using (var writer = new Utf8JsonWriter(bufferWriter))
? ? ? ? {
? ? ? ? ? ? element.WriteTo(writer);
? ? ? ? }
? ? ? ? return JsonSerializer.Deserialize(bufferWriter.WrittenSpan, returnType, options);
? ? }
? ? public static object ToObject(this JsonDocument document, Type returnType, JsonSerializerOptions options = null)
? ? {
? ? ? ? if (document == null)
? ? ? ? {
? ? ? ? ? ? throw new ArgumentNullException(nameof(document));
? ? ? ? }
? ? ? ? return document.RootElement.ToObject(returnType, options);
? ? }? ? ? ?
}

TA貢獻1789條經驗 獲得超10個贊
.NET 6引入了System.Text.Json.Nodes命名空間,它提供了一種使用與 Json.Net 幾乎完全相同的語法來執行此操作的方法:
var str = ""; // some json string
var node = JsonNode.Parse(str);
var myClass = node["SomeProperty"].Deserialize<SomeClass>();
命名空間包括 4 個新類型:JsonNode
、JsonArray
、JsonObject
、 和JsonValue
可用于訪問或修改 DOM 中的值。JsonNode
是其他三種類型的基類。
Deserialize
中列出的擴展方法也已添加到 上進行操作,例如:JsonNode
public?static?TValue??Deserialize<TValue>(this?JsonNode??node,?JsonSerializerOptions??options?=?null);
JsonNode
不是一次性的,因此您不需要使用using
語法。
使用AsObject()
or分別AsArray()
解析為JsonObject
or?JsonArray
:
// parse array
JsonArray arr = JsonNode.Parse(@"[{""Name"": ""Bob"", ""Age"":30}]").AsArray();
// parse object
JsonObject obj = JsonNode.Parse(@"{""Name"": ""Bob"", ""Age"":30}").AsObject();
// get a value
var date = JsonNode.Parse(@"{""Date"":""2021-12-21T13:24:46+04:00""}")["Date"].GetValue<DateTimeOffset>();
一旦 json 被解析,就可以導航、過濾和轉換 DOM 和/或應用于Deserialize<T>()映射到您的具體類型。
要序列化回 json 字符串,您可以使用ToJsonString(),例如:
string innerNodeJson = node["SomeProperty"].ToJsonString();
- 4 回答
- 0 關注
- 339 瀏覽
添加回答
舉報