Newtonsoft JSON - 动态对象

Posted

技术标签:

【中文标题】Newtonsoft JSON - 动态对象【英文标题】:Newtonsoft JSON - Dynamic Objects 【发布时间】:2012-11-20 22:46:09 【问题描述】:

我正在使用 Newtonsoft JSON 库对传入的原始 JSON 执行动态反序列化,并发现了一些我无法解释的东西。

起点是以下 JSON 字符串:


  "task": 
    "dueDate": "2012-12-03T00:00:00"
  

没什么太复杂的...

在代码中我正在这样做:

var dyn = JsonConvert.DeserializeObject<dynamic>(rawJson);
DateTime dueDate = dyn.task.dueDate.Value;

这段代码已经存在了几个月并且运行良好,但是在最近的测试版本中,我们看到了以下错误:

'Newtonsoft.Json.Linq.JObject' 不包含对 “任务”

堆栈跟踪:在 CallSite.Target(Closure , CallSite , Object ) 在 System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,Tret](CallSite 站点,T0 arg0)

现在这很奇怪,如果我更改上面的代码,一切都会重新开始工作:

DateTime dueDate = dyn.task.dueDate.Value;

DateTime dueDate = dyn["task"]["dueDate"].Value;

因此,尽管这是“已修复”,但我不明白为什么要修复它以及可能的原因是什么。有人有什么想法吗

【问题讨论】:

您是否更改了您使用的 Json.NET 版本? 不,这是我的第一个想法 - 查看代码和库的更改历史记录显示实时(和正在工作)的内容没有变化 您确定这不是“第一次机会例外” - 典型的动态(也许您在错误登录等中增加了详细信息级别)? 使用最新版本的 Json.NET 进行的小测试表明您的代码可以正常工作 - 所以这里没有回归。 经过进一步调查,这是某种环境问题,我已将这些库放到开发盒中,它们运行良好。所以这是测试环境的问题,可能是 .NET 版本之类的 【参考方案1】:

你可以试试这个:

dynamic task = JObject.Parse(rawJson);

文档:Querying JSON with dynamic

【讨论】:

因为他想了解为什么它在提供的示例中不起作用,因为它应该适用于提供的示例。 它的小问题:您必须知道它是对象还是数组,并使用 JObject.Parse() 或 JArray.Parse()。换句话说,您需要事先知道您是在反序列化数组还是对象。动态 t1 = JObject.Parse(@"['a':10]"); //失败动态 t2 = JArray.Parse(@"['a':10]"); //传递动态 t3 = JObject.Parse(@"'a':10"); //传递动态 t4 = JArray.Parse(@"'a':10"); //失败【参考方案2】:

在我的情况下,我发现我捕获了第一次机会异常,所以虽然抛出了这个异常,但实际上并没有阻止我的代码执行。

仍然很高兴知道为什么 Json.NET 反序列化的某些内容会发生这种情况,但不是所有内容。例如,我有一个动态对象,我在单元测试中使用 json.net 序列化,然后反序列化序列化的内容。序列化的内容看起来与在运行时会导致引发运行时绑定程序异常的内容相同。

【讨论】:

【参考方案3】:

我遇到了同样的问题。

Json.NET 6.0.4 导致此问题。您应该将其更改为 Json.Net 6.0.5。 任何项目都不应引用 Json.NET 6.0.4。

转到工具 -> NuGet 包管理器 -> 管理 NuGet 包以获取解决方案... 并检查是否有任何项目使用 Json.NET 6.0.4,修复它们。

【讨论】:

记录在案,与 Json.NET 6.0.3 相同的问题。修复了最新版本 7.0.1。 顺便说一句,我下载了 Newtonsoft.JSON 源并搜索了“任务”。在测试方法中输入了 OP 的精确原始 JSON……谁知道为什么会发生这种情况,但 Newtonsoft 中的某个人一直在阅读此内容。看起来底线是这是(或曾经是)库的错误。【参考方案4】:

这绝对是一些参考问题,我只是遇到了同样的问题,原来问题是我已经将包文件夹添加到项目中,以便我可以在 VSS 中签入它(对不起,强制性),尽快我从 Visual Studio 中删除了 packages 文件夹,它开始正常工作

【讨论】:

VSS...哎哟!很抱歉听到这个消息。【参考方案5】:

这个问题持续了一段时间,事实证明,使用的 DLL 是为不支持动态的 .NET 3.5 编译的...确保您的 DLL 是为 .NET 4.5 及更高版本编译的

【讨论】:

【参考方案6】:

我在使用 Json.NET 的应用程序中遇到了同样的问题。该问题仅在一台特定机器上再次出现,结果证明该机器在 GAC 中安装了另一个版本的 Json.NET。从 GAC 中删除后,该应用程序开始正常工作。

【讨论】:

这对我来说也是同样的问题!【参考方案7】:

我有一个类似的问题,因为我有一个项目正在做很多动态的事情。

我把它缩小到...... JsonElement 和序列化。使用 Dynamic,底层类型存在,序列化为 JSON 应该将该对象序列化为什么?动态可以是:字符串、数字、日期时间、真、假等,所以他们也需要放一些元数据,这样当你提到动态时,它就知道在序列化时

所以...当您序列化时,我相信动态会转换为 JsonElement - 指定 ValueKind 和 Value 作为属性。

当您反序列化时,事情变得复杂...... JSON 到 C# 将匹配类中的属性,如果它作为目标是动态的 - 需要根据 JSON 元素信息恢复动态。

这是事情变得模糊的地方,但我可以肯定,如果您查看 Serialzation 并看到 ValueKind,那么您很可能在另一边遇到问题。

还请观看 Text.Json (MS) 反序列化和序列化,因为我相信它们在 newtonsoft 和 MS 处理动态序列化和反序列化的方式上有所不同。

【讨论】:

以上是关于Newtonsoft JSON - 动态对象的主要内容,如果未能解决你的问题,请参考以下文章

newtonsoft动态修改JObject

使用Newtonsoft.Json.dll(JSON.NET)动态解析JSON.net 的json的序列化与反序列化

请教Newtonsoft.Json序列化对象,怎么动态的选择要被序列化的字段

“Newtonsoft.Json.JsonConvert”类型存在于“Newtonsoft.Json.dll”和“NuGetApi2.dll”中

c# Newtonsoft.Json封装

Newtonsoft.Json输出Json时动态忽略属性