我正在使用Newtonsoft对一个已知的JSON对象进行格式化,并从中检索一些值(如果它们存在的话)。
关键是对象结构可能会不断变化,所以我使用dynamic来遍历结构并检索值。由于对象结构不断变化,我使用空条件运算符来遍历JSON。
代码如下所示
dynamic jsonMeta = JsonConvert.DeserializeObject<dynamic>(jsonScript);
string gVal = jsonMeta.a?.b?.c?.d?.e?.f?.g?.Value ?? ""
这样做的全部思想是以空安全的方式遍历对象,这样如果成员不存在,它的计算结果为null
,并为其分配一个默认值,而不会抛出异常。但是我看到的是,如果成员d是null
,我会得到一个异常'Newtonsoft.Json.Linq.JValue' does not contain a definition for 'e'
。
我的理解是,虽然d
的 Value 是null
,但它的类型是JValue
,所以这就是null条件运算符不起作用的原因,但当它试图访问d
内部的成员e
时,它会抛出异常。
那么我的问题是如何在C#中实现这一点?有没有一种简单的方法可以访问JSON成员,而不需要知道JSON结构,或者是一种相对简单的方法?
2条答案
按热度按时间xmd2e60i1#
不幸的是,由于NewtonSoftJSON.NET的设计限制,当将其用作动态转换时,它不能使用空合并或空条件运算符,正如我在上面的问题中所示的那样。
我发现的一个解决方案是使用System.Web.Helpers.Json,这个实现允许你做我上面试图做的事情,而不会遇到JSON.NET抛出的异常,因为它在运行时评估成员的方式导致了一种简单的方法来访问动态JSON结构的成员。另外,您不需要为成员引用
Value
,它是隐式的。但是,您需要根据您使用的Visual Studio版本单独安装程序集(这对于JSON.NET也是必需的)。使用VS 2019,只需通过IDE错误助手单击即可轻松安装它。关于它的更多细节在这里:Where can I find System.Web.Helpers, System.Web.WebPages, and System.Web.Razor?
Json.Decode
的局限性是它不能处理重复的键(抛出异常),并且对它可以解析的字符数有最大限制(MaxJsonLength错误),这可以由inconvenient来修复。wpx232ag2#
另一种选择是使用
dynamic
ExpandoObject
,同时使用Newtonsoft.Json对JSON进行格式化。这允许您在动态对象上使用空条件运算符和空合并运算符。但是这有一个限制,* 如果它访问一个不存在的成员,
ExpandoObject
将抛出一个异常 *(它是一个密封的类,这个行为是硬编码的)。所以为了解决这个问题,我写了一个自定义的SafeExpandoObject
类,它 Package 了ExpandoObject
,允许你访问所有/不存在的成员而不会抛出异常,当你试图访问一个不存在的成员时,它会返回null
。你可以在这里找到代码:https://codereview.stackexchange.com/questions/287243/wrapping-an-expandoobject-within-a-safeexpandoobject
这样使用:
另一点需要注意的是,你不能像
jsonMeta["@name"]
那样使用ExpandoObject
的直接索引。要克服这个限制,您需要实现
SafeExpandoObject
的IDictionary
接口,以允许直接索引,或者将ExpandoObject
转换为IDictionary<string, object>
,然后像下面这样索引它: