将对象转换为 System.Text.Json.JsonElement

ryt*_*isk 10 c# json system.text.json

假设我有一个类型的对象:

public class MyClass
{
    public string Data { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我需要将其转换为 System.Text.Json.JsonElement。我找到的唯一方法是:

var json = JsonSerializer.Serialize(new MyClass { Data = "value" });

using var document = JsonDocument.Parse(json);

var jsonElement = document.RootElement;
Run Code Online (Sandbox Code Playgroud)

我必须先序列化它然后再解析它,这似乎很奇怪。有没有更好的方法呢?

以前我是JObject从 Newtonsoft.Json使用的,我可以这样做:

var jobject = JObject.FromObject(new MyClass { Data = "value" });
Run Code Online (Sandbox Code Playgroud)

dbc*_*dbc 10

等效于的方法JObject.FromObject()目前在System.Text.Json. 有一个关于此的开放增强功能,目前针对Future

在此期间,你可以通过序列化到中间获得更好的性能byte数组,而不是一个字符串,因为两者JsonDocumentUtf8JsonReader直接与工作byte的跨度,而不是字符串或char跨度,就像这样:

public static partial class JsonExtensions
{
    public static JsonDocument JsonDocumentFromObject<TValue>(TValue value, JsonSerializerOptions options = default) 
        => JsonDocumentFromObject(value, typeof(TValue), options);

    public static JsonDocument JsonDocumentFromObject(object value, Type type, JsonSerializerOptions options = default)
    {
        var bytes = JsonSerializer.SerializeToUtf8Bytes(value, options);
        return JsonDocument.Parse(bytes);
    }

    public static JsonElement JsonElementFromObject<TValue>(TValue value, JsonSerializerOptions options = default)
        => JsonElementFromObject(value, typeof(TValue), options);

    public static JsonElement JsonElementFromObject(object value, Type type, JsonSerializerOptions options = default)
    {
        using var doc = JsonDocumentFromObject(value, type, options);
        return doc.RootElement.Clone();
    }
}
Run Code Online (Sandbox Code Playgroud)

然后像这样调用它:

using var doc = JsonExtensions.JsonDocumentFromObject(new MyClass { Data = "value" });
Run Code Online (Sandbox Code Playgroud)

或者,如果您需要在using语句范围之外使用根元素:

var element = JsonExtensions.JsonElementFromObject(new MyClass { Data = "value" });
Run Code Online (Sandbox Code Playgroud)

笔记:

  • JsonDocumentIDisposable,事实上必须被处置,因为,根据文档

    此类利用池内存中的资源来最大程度地减少垃圾收集器 (GC) 在高使用率场景中的影响。未能正确处置此对象将导致内存无法返回到池中,这将增加框架各个部分的 GC 影响。

    当您需要JsonElement在文档的生命周期之外使用文档中的 a 时,您必须克隆它。

    JsonExtensions.JsonElementFromObject()上面的方法会自动处理这个问题。

  • string根据文档,序列化为中间 Utf8 字节序列可能比序列化为 a 的性能更高:

    序列化为 UTF-8 比使用基于字符串的方法快 5-10%。不同之处在于字节(如 UTF-8)不需要转换为字符串(UTF-16)。

  • 有关逆方法,请参阅System.Text.Json.JsonElement ToObject 解决方法

演示小提琴在这里