使用System.Text.Json反序列化匿名类型

29

我正在更新一些针对.NET Core 3.x的应用程序,作为其中的一部分,我正在尝试从Json.NET迁移到新的System.Text.Json类。使用Json.NET,我可以像这样反序列化匿名类型:

var token = JsonConvert.DeserializeAnonymousType(jsonStr, new { token = "" }).token;

在新的命名空间中是否有等效的方法?


2
尚未。匿名类型对象缺少无参数构造函数,因此尝试反序列化为匿名类型会抛出异常。演示: https://dotnetfiddle.net/BLsmwg。 - dbc
相关增强(开放):JsonSerializer 支持不可变类和结构体。#38569,标记为 里程碑: 未来,5.0 - dbc
你可以使用自定义的 JsonConverter 来实现,但是以通用的方式来做会比较棘手和复杂。 - dbc
2个回答

33
截至 .Net 5.0,System.Text.Json支持反序列化不可变类型(包括匿名类型)。来自如何使用不可变类型和非公共访问器与System.Text.Json的说明:

System.Text.Json可以使用带参数的构造函数,因此可以反序列化不可变类或结构。对于一个类,如果唯一的构造函数是带参数的,则将使用该构造函数。

由于匿名类型只有一个构造函数,因此现在可以成功进行反序列化。为此,请定义一个辅助方法,如下所示:
public static partial class JsonSerializerExtensions
{
    public static T? DeserializeAnonymousType<T>(string json, T anonymousTypeObject, JsonSerializerOptions? options = default)
        => JsonSerializer.Deserialize<T>(json, options);

    public static ValueTask<TValue?> DeserializeAnonymousTypeAsync<TValue>(Stream stream, TValue anonymousTypeObject, JsonSerializerOptions? options = default, CancellationToken cancellationToken = default)
        => JsonSerializer.DeserializeAsync<TValue>(stream, options, cancellationToken); // Method to deserialize from a stream added for completeness
}

现在你可以做:

var token = JsonSerializerExtensions.DeserializeAnonymousType(jsonStr, new { token = "" }).token;

这里提供演示版的代码 链接


2
请尝试使用我编写的库,作为System.Text.Json的扩展,提供缺失的功能:https://github.com/dahomey-technologies/Dahomey.Json
您将找到对匿名类型的支持。
通过在JsonSerializerOptions上调用命名空间Dahomey.Json中定义的SetupExtensions扩展方法来设置json扩展。
JsonSerializerOptions options = new JsonSerializerOptions();
options.SetupExtensions();

然后使用JsonSerializerExtensions静态类型对您的类进行序列化:
var token = JsonSerializerExtensions.DeserializeAnonymousType(jsonStr, new { token = "" }, options).token;

9
很好,但对我们来说,System.Text.Json的吸引力在于消除了另一个第三方依赖。如果我们必须添加一个库才能使它工作,那么还不如坚持使用Newtonsoft。 - superstator
3
我完全理解你的观点。我写这个库的原因是因为System.Text.Json更快,而且在特定主题(多态支持)上比Newtonsoft不够灵活。 - Michaël Catanzariti
没有原型的情况下有没有其他方法? 我有这样一种情况,需要处理用户输入的结构未知的JSON数据源。我无法创建原型,因为不知道他们的json数据结构会是什么样子。我计划将其作为一个假定的扁平数组进行处理,其中包含我将枚举字段的对象。 - computrius
是的,你可以这样做,但我们不再谈论匿名类型了。你可以使用JsonObject,它的工作方式类似于DOM对象。 - Michaël Catanzariti

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接