为什么在我调用 JsonConvert.DeserializeObject() 时将 JArray 分配给 var 会失败?
Why does assigning a JArray to a var fail when I call JsonConvert.DeserializeObject()?
在这行代码中:
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 不是一个数组,它是一个 包含 数组 (results
) 的对象。但它实际上比这更复杂:您查找的 certification
字符串嵌套在第二个 release_dates
数组的更下方。
如果您使用 JSON 并使用 JSON validator/beautifier 重新格式化它,它应该会变得更清晰:
{
"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"];
// ...
}
}
Fiddle: https://dotnetfiddle.net/SMzQTw
如果您只需要一项,这里有一个快捷方式。将 SelectToken
方法与递归下降运算符 (..
) 结合使用,如下所示:
var obj = JsonConvert.DeserializeObject<JObject>(s);
_currentMPAARating = (string)obj.SelectToken("..certification");
Fiddle: https://dotnetfiddle.net/S1ScLO
但请注意,以上只会 return 第一场比赛。如果您希望获得多项认证,可以使用 SelectTokens
(复数)代替:
var obj = JsonConvert.DeserializeObject<JObject>(s);
var ratings = obj.SelectTokens("..certification").Select(t => (string)t).ToList();
Fiddle: https://dotnetfiddle.net/zyjNnJ
在这行代码中:
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 不是一个数组,它是一个 包含 数组 (results
) 的对象。但它实际上比这更复杂:您查找的 certification
字符串嵌套在第二个 release_dates
数组的更下方。
如果您使用 JSON 并使用 JSON validator/beautifier 重新格式化它,它应该会变得更清晰:
{
"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"];
// ...
}
}
Fiddle: https://dotnetfiddle.net/SMzQTw
如果您只需要一项,这里有一个快捷方式。将 SelectToken
方法与递归下降运算符 (..
) 结合使用,如下所示:
var obj = JsonConvert.DeserializeObject<JObject>(s);
_currentMPAARating = (string)obj.SelectToken("..certification");
Fiddle: https://dotnetfiddle.net/S1ScLO
但请注意,以上只会 return 第一场比赛。如果您希望获得多项认证,可以使用 SelectTokens
(复数)代替:
var obj = JsonConvert.DeserializeObject<JObject>(s);
var ratings = obj.SelectTokens("..certification").Select(t => (string)t).ToList();
Fiddle: https://dotnetfiddle.net/zyjNnJ