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

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

public class MyClass
{
    public string Data { get; set; }
}

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

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

using var document = JsonDocument.Parse(json);

var jsonElement = document.RootElement;

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

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

var jobject = JObject.FromObject(new MyClass { Data = "value" });
stack overflow Convert object to System.Text.Json.JsonElement
原文答案
author avatar

接受的答案

在.NET 6 中,正在将方法添加到 JsonSerializer 中,以直接将对象直接序列化为 JsonElementJsonDocument

public static partial class JsonSerializer
{
    public static JsonDocument SerializeToDocument<TValue>(TValue value, JsonSerializerOptions? options = null);
    public static JsonDocument SerializeToDocument(object? value, Type inputType, JsonSerializerOptions? options = null);
    public static JsonDocument SerializeToDocument<TValue>(TValue value, JsonTypeInfo<TValue> jsonTypeInfo);
    public static JsonDocument SerializeToDocument(object? value, Type inputType, JsonSerializerContext context);

    public static JsonElement SerializeToElement<TValue>(TValue value, JsonSerializerOptions? options = null);
    public static JsonElement SerializeToElement(object? value, Type inputType, JsonSerializerOptions? options = null);
    public static JsonElement SerializeToElement<TValue>(TValue value, JsonTypeInfo<TValue> jsonTypeInfo);
    public static JsonElement SerializeToElement(object? value, Type inputType, JsonSerializerContext context);
}

因此,在.NET 6中,您将能够做到:

using var jsonDocument = JsonSerializer.SerializeToDocument(new MyClass { Data = "value" });

或者

var jsonElement = JsonSerializer.SerializeToElement(new MyClass { Data = "value" });

笔记:

  • JsonSerializerContextJsonTypeInfo<T> 在.NET 6中新公开,并提供与JSON Serialization有关的一组类型或单一类型 T 的元数据。使用元数据和在编译时生成的代码序列化时使用它们。有关详细信息,请参见 Try the new System.Text.Json source generator

  • JsonDocumentIDisposable ,实际上必须处置,因为,根据 docs

    JsonDocument 将数据的内存视图构建到汇总的缓冲区中。因此,与 JObjectJArray 从newtonsoft.json, JsonDocument type type internement IDisposable type using ,并且需要在 JsonDocument.Parse() block中使用。

    在您的示例代码中,您不处理 .NET 6 RC1 返回的文档,但您应该。

*新方法应在 JObject.FromObject() 中存在。

在.net 5和更早的当前在 System.Text.Json 中的框中不可用 Future 等效的方法。对此有一个开放的增强,目前针对 We should be able serialize and serialize from DOM #31274

  • byte

在中期,您可以通过序列化到中间 JsonDocument 数组而不是字符串来获得更好的性能,因为 Utf8JsonReaderbyte 都可以直接与 char 跨度合作,而不是strings或{jxm = jxm = jxm = }跨越,就像这样:

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, type, 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();
    }
}

然后称其为:

using var doc = JsonExtensions.JsonDocumentFromObject(new MyClass { Data = "value" });

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

var element = JsonExtensions.JsonElementFromObject(new MyClass { Data = "value" });

笔记:

*如上所述,创建后需要处置 JsonDocument 。如 JsonExtensions.JsonElementFromObject() 中的建议,上面的 documentation 扩展方法正确处理其内部文档并返回根元素的克隆。

*序列化到中间UTF8字节序列可能比序列化到 string 更具性能,因为,根据 docs

>与使用基于字符串的方法相比,序列化与UTF-8的序列化约为5-10 %。区别是因为字节(作为UTF-8)不需要转换为字符串(UTF-16)。

*有关逆方法,请参见 [System.Text.Json.JsonElement ToObject workaround](https://stackoverflow.com/q/58138793/3744182)

演示小提琴 here


答案:

作者头像

.NET 5中的一种光滑的方法是:

private JsonElement JsonElementFromObject(object value)
{
    var jsonUtf8Bytes = JsonSerializer.SerializeToUtf8Bytes(value, new JsonSerializerOptions());
    using var doc = JsonDocument.Parse(jsonUtf8Bytes);
    return doc.RootElement.Clone();
}

脚步:

1.将值转换为JSON字符串,编码为UTF-8字节( SerializeToUtf8Bytes )。
2.解析JSON字符串( JsonDocument.Parse )。
3.返回根元素。