从类型化对象复制的动态对象具有空值

Dynamic object copied from a typed object has a null value

我正在开发一个通用的 restApi class 交互器来处理我公司的网络服务,但发现了一些奇怪的东西。 当我使用动态类型使事情变得灵活时 Json 启用我注意到一些属性显示为空,如果在我执行显式转换时它不够奇怪我得到了正确的值。 我正在使用来自 Newtonsoft.Json 的 Json 6.0.4 和 .NET Framework 4.6.2.

你们知道为什么会出现这种问题吗?

按照下面的一小段代码来说明我在说什么,你可以看到 vars d_type_2 和 j_type_2.

中的错误
static void Main(string[] args)
    {
        var jsonString = File.ReadAllText("Json4.txt");
        var jsonObject = JValue.Parse(jsonString);

        var JsonObject_1 = jsonObject;
        dynamic JsonObject_2 = jsonObject;


        dynamic d_type_1 = JsonObject_1.Type;
        dynamic d_type_2 = JsonObject_2.Type;

        JTokenType j_type_1 = JsonObject_1.Type;
        JTokenType j_type_2 = JsonObject_2.Type;

    }

我尝试了两种代码。首先,我拿了一个 json 对象,对其进行了解析并可以重现您的案例。在此之后我尝试使用 json 数组,它为 JsonObject_2.Type.

正确返回了 Array

这种行为看起来很奇怪,所以我深入研究了 Newtonsoft 的 source

当我们使用库知道是 JObject 类型的 JsonObject_1 时,它 returns .Type 属性 的值为 Object。 以下是 JObject

源代码中的 Type 属性 getter
public override JTokenType Type => JTokenType.Object;

但是对于 dynamic 它采取了不同的路径。

在去那里之前,重要的是要知道当我们去 JValue.Parse(jsonString) 时会发生什么。 如果 jsonString 持有 json 对象,Newtonsoft 库会从 'jsonString' 中提取 key,value 对并将其存储在私有 Dictionary 中。这对我接下来要解释的内容很有用。

现在,为了使用“动态”,Newtonsoft 使用了 .Net 中的 DLR 功能。当我们尝试读取此类 dynamic 对象的任何成员 属性 时, 它通过 JObject DynamicProxyTryGetMember 方法。 根据这个方法的实现,它只在我上面提到的私有字典中搜索。如果 属性 没有找到它 returns null.Type 因此 returns null 因为它在 Dictionary.

中不可用

尝试以下(有趣的)代码变体,看看您在 d_type_1d_type_2 中得到了什么 :)

 static void Main(string[] args)
    {
        var jsonString = " {'key1':'value1','key2':'value2','Type':'value3'} ";
        var jsonObject = JValue.Parse(jsonString);
        var JsonObject_1 = jsonObject;
        dynamic JsonObject_2 = jsonObject;
        
        dynamic d_type_1 = JsonObject_1.Type;
        dynamic d_type_2 = JsonObject_2.Type;
    }