在.NET 6中,
JsonSerializer
将添加扩展方法,可直接从
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
is disposable. According to the documentation, This class utilizes resources from pooled memory... failure to properly dispose this object will result in the memory not being returned to the pool, which will increase GC impact across various parts of the framework.
So, be sure to declare your jDoc
with a using
statement.
The new methods should be present in .NET 6.0 Preview RC1.
They were added in response to the enhancement request We should be able serialize and serialize from DOM #31274, which has been closed.
Similar extension methods were added for the new JsonNode
mutable JSON document node as well
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);
}
}
这里有一个演示fiddle 链接。
using
语句处理Utf8JsonWriter writer
的释放,并根据文档中的说明,dispose 方法 对于 IBufferWriter,在已经写入的基础上使底层IBufferWriter<T>
前进;而 flush 方法 也 在已经写入的基础上使底层IBufferWriter<T>
前进。两者都进行似乎是不必要的。 - dbcusing var writer = new Utf8JsonWriter(bufferWriter);
这样一来,Dispose
方法只会在函数结束时调用,这完全改变了代码的行为,需要使用Flush
来修复它。一对括号产生的差别真是大啊! - mclaytonJsonSerializer
内部反序列化 utf8 字节序列,因此JsonSerializer.Deserialize<TValue>(string json, ...)
在反序列化之前会进行 utf8 转码。我的方法直接跳过了来回转码的步骤。 - dbcArrayBufferWriter
似乎是 .NET Core 的东西。在 .NET Framework 4.8 中工作时,我能否用Microsoft.Toolkit.HighPerformance
nuget 包中的ArrayPoolBufferWriter
替换它? - dotNET