我收到间歇性错误'Newtonsoft.Json.Linq.JValue'不包含'Contains'的定义



执行.NET C#代码时出现间歇性错误。以下是错误。

Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'Newtonsoft.Json.Linq.JValue' does not contain a definition for 'value'

下面是我正在使用的代码-

dynamic obj = JsonConvert.DeserializeObject(response);
string value = obj.responseObject.value.token;

当我尝试执行上面的代码-时,我得到了这个错误

Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'Newtonsoft.Json.Linq.JValue' does not contain a definition for 'value'

请帮忙,我们将不胜感激。非常感谢。

您的问题是您试图反序列化JSON,通常看起来如下所示:

{"responseObject" : { "value" : { "token" : "some token" } } }

通过使用Json.NET的动态运行时绑定到Json属性:

dynamic obj = JsonConvert.DeserializeObject(response);
string value = obj.responseObject.value.token;

在您的代码工作的情况下,JSON包含您期望的属性和您期望的类型。但是,当您的JSON无法确认您期望的模式时——特别是"value"的值是原子JSON值或null而不是嵌套对象——那么Newtonsoft的动态绑定代码将失败,并显示您看到的错误。例如,给定以下两个JSON示例:

{"responseObject" : { "value" : "some atomic value such as an error message" } }
{"responseObject" : { "value" : null } }

则CCD_ 3将抛出CCD_。

在这里演示小提琴#1。

那么,对于解决方法,您有哪些选择?

dynamic绑定有一个方便的语法,看起来很诱人,但当您使用dynamic时,您将失去所有编译时的错误检查,并且当您的对象与您期望的不完全一样时,您经常会发现自己出现完全无法理解的错误。由于Json.NET的dynamic反序列化实际上反序列化为LINQ到Json的JToken层次结构,因此应该显式地这样做:

var obj = JsonConvert.DeserializeObject<JObject>(response);

现在要以容错方式访问obj.responseObject.value.token,您的选项包括:

  1. 使用SelectToken():

    var value = (string)obj.SelectToken("responseObject.value.token");
    

    SelectToken()比动态绑定更具容错性,并且如果指定路径上不存在令牌,则仅返回null

  2. 使用JTtoken索引器并明确检查obj["responseObject"]?["value"]是否为JSON对象:

    var value = (string)(obj["responseObject"]?["value"] as JObject)?["token"];
    
  3. 作为#2的变体,您可以引入一些扩展方法如下:

    public static partial class JsonExtensions
    {
    public static JObject AsJObject(this JToken @in) => @in.As<JObject>();
    public static TJToken As<TJToken>(this JToken @in) where TJToken : JToken => @in as TJToken;
    }
    

    并执行:

    var value = (string)obj["responseObject"].AsJObject()?["value"].AsJObject()?["token"];
    
  4. 您可以使用Json.NET Schema在解析之前验证Json。但是请注意,Json.NET Schema不是免费的。

演示小提琴#2,在此演示选项1-3。

最新更新