首页 > 解决方案 > 当我调用 JsonConvert.DeserializeObject() 时,为什么将 JArray 分配给 var 失败?

问题描述

在这行代码上:

var arr = JsonConvert.DeserializeObject<JArray>(s);

...我得到,“无法将 'Newtonsoft.Json.Linq.JObject' 类型的对象转换为 'Newtonsoft.Json.Linq.JArray' 类型。”

我将该行更改为:

JArray arr = JsonConvert.DeserializeObject<JArray>(s);      

...并得到相同的错误消息。

我把它改成这样:

var arr = JsonConvert.DeserializeObject<JObject>(s);

...它甚至不会编译。

此时调用(在字符串 s 中)读取的值是:

{"id":347745,"results":[{"iso_3166_1":"US","release_dates":[{"certification":"","iso_639_1":"","note":"","release_date":"1936-12-12T00:00:00.000Z","type":3}]}]}

我想要的只是“认证”的价值;在这种情况下,认证值是一个空字符串(“certification”:“”)

在上下文中,代码是:

. . .
try
{
    var webRequest = (HttpWebRequest)WebRequest.Create(RESTStringToGetMPAARatingForMovieId);
    webRequest.Method = "GET";  
    var webResponse = (HttpWebResponse)webRequest.GetResponse();
    if ((webResponse.StatusCode == HttpStatusCode.OK) && (webResponse.ContentLength > 0))
    {
        StreamReader streamReader = new StreamReader(webResponse.GetResponseStream());
        string s = streamReader.ReadToEnd();
        var arr = JsonConvert.DeserializeObject<JArray>(s);
        //JArray arr = JsonConvert.DeserializeObject<JArray>(s);
        //var arr = JsonConvert.DeserializeObject<JObject>(s);
        foreach (JObject obj in arr)
        {
            _currentMPAARating = (string)obj["certification"];
            . . .
        }
    }
    else
    {
        MessageBox.Show(string.Format("Status code == {0}, Content length == {1}",
          webResponse.StatusCode, webResponse.ContentLength));
    }    
}
catch (Exception ex)
{
    MessageBox.Show(ex.Message);
}

标签: json.netjson-deserializationjsonconvert

解决方案


您的 JSON 不是数组,它是一个包含数组 ( results) 的对象。但实际上比这更复杂:certification您寻找的字符串嵌套在第二个release_dates数组中的更下方。

如果您获取 JSON 并使用 JSON 验证器/美化器重新格式化它,它应该会变得更加清晰:

{
  "id": 347745,
  "results": [
    {
      "iso_3166_1": "US",
      "release_dates": [
        {
          "certification": "",
          "iso_639_1": "",
          "note": "",
          "release_date": "1936-12-12T00:00:00Z",
          "type": 3
        }
      ]
    }
  ]
}

因此,要使用常规foreach循环获取您要查找的数据,您需要如下代码:

var obj = JsonConvert.DeserializeObject<JObject>(s);
var resultArr = (JArray)obj["results"];
foreach (JObject resultObj in resultArr)
{
    var releaseDatesArr = (JArray)resultObj["release_dates"];
    foreach (JObject releaseDateObj in releaseDatesArr)
    {
        _currentMPAARating = (string)releaseDateObj["certification"];
        // ...
    }
}

小提琴:https ://dotnetfiddle.net/SMzQTw

如果您只需要一件物品,这里有一个捷径。使用SelectToken带有递归下降运算符 ( ..) 的方法,如下所示:

var obj = JsonConvert.DeserializeObject<JObject>(s);
_currentMPAARating = (string)obj.SelectToken("..certification");

小提琴:https ://dotnetfiddle.net/S1ScLO

但请注意,上面只会返回第一个匹配项。如果您期望获得多个认证,则可以改用SelectTokens(复数):

var obj = JsonConvert.DeserializeObject<JObject>(s);
var ratings = obj.SelectTokens("..certification").Select(t => (string)t).ToList();

小提琴:https ://dotnetfiddle.net/zyjNnJ


推荐阅读