为了账号安全,请及时绑定邮箱和手机立即绑定

System.Text.Json.JsonElement ToObject 解决方法

System.Text.Json.JsonElement ToObject 解决方法

PHP
12345678_0001 2024-01-20 15:50:11
我想知道Json.NETToObject<>()中System.Text.Json的方法的等效项。使用 Json.NET,您可以使用任何JToken并将其转换为类。例如:var str = ""; // Some JSON stringvar jObj = JObject.Parse(str);var myClass = jObj["SomeProperty"].ToObject<SomeClass>();我们如何使用 .NET Core 3 的新功能来做到这一点System.Text.Json?var str = ""; // Some JSON stringvar jDoc = JsonDocument.Parse(str);var myClass = jDoc.RootElement.GetProperty("SomeProperty"). <-- now what??最初,我想我只是将JsonElement返回的值转换jDoc.RootElement.GetPRoperty("SomeProperty")为字符串,然后反序列化该字符串。但我觉得这可能不是最有效的方法,而且我无法真正找到有关以其他方式执行此操作的文档。
查看完整描述

4 回答

?
婷婷同学_

TA贡献1844条经验 获得超8个赞

在 .NET 6 中,添加了扩展方法以直接从orJsonSerializer反序列化对象:JsonElementJsonDocument

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);

    }

}

演示小提琴在这里




查看完整回答
反对 回复 2024-01-20
?
慕娘9325324

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>();


查看完整回答
反对 回复 2024-01-20
?
jeck猫

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);

    }       

}


查看完整回答
反对 回复 2024-01-20
?
至尊宝的传说

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 个新类型:JsonNodeJsonArrayJsonObject、 和JsonValue可用于访问或修改 DOM 中的值。JsonNode是其他三种类型的基类。

Deserialize中列出的扩展方法也已添加到 上进行操作,例如:JsonNode

public static TValue? Deserialize<TValue>(this JsonNode? node, JsonSerializerOptions? options = null);

JsonNode不是一次性的,因此您不需要使用using语法。

使用AsObject()or分别AsArray()解析为JsonObjector 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();


查看完整回答
反对 回复 2024-01-20
  • 4 回答
  • 0 关注
  • 50 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信