我正在尝试使用Delphi XE7从Twitter API解析JSON结果。我得到了一个"无效的类类型转换"错误,但是我使用在线验证程序检查JSON,这没关系。
以下是JSON结果:
[
{
"trends":
[
{
"name":"#OneDirectionIsOverParty",
"url":"http://twitter.com/search?q=%23OneDirectionIsOverParty",
"promoted_content":null,
"query":"%23OneDirectionIsOverParty",
"tweet_volume":410022
},
{
"name":"#TheDarkKnight",
"url":"http://twitter.com/search?q=%23TheDarkKnight",
"promoted_content":null,
"query":"%23TheDarkKnight",
"tweet_volume":null
},
{
"name":"#QuintaComOClubeSdv",
"url":"http://twitter.com/search?q=%23QuintaComOClubeSdv",
"promoted_content":null,
"query":"%23QuintaComOClubeSdv",
"tweet_volume":23756
}
],
"as_of":"2016-07-21T20:14:13Z",
"created_at":"2016-07-21T20:08:31Z",
"locations":
[
{
"name":"Worldwide",
"woeid":1
}
]
}
]
这是我的解析功能:
procedure ParseJSON(const JSON: string);
var
JSONObject: TJSONObject;
MessageText: TJSONArray;
NodeDetails: TJSONObject;
MsgDetail: TJSONString;
I: Integer;
Item: TListItem;
begin
JSONObject := TJSONObject.ParseJSONValue(TEncoding.UTF8.GetBytes(JSON), 0) as TJSONObject;
MessageText := JSONObject.Get('trends').JSONValue as TJSONArray;
for I := 0 to TJSONArray(MessageText).Size - 1 do
begin
Item := Form1.ListView1.Items.Add;
NodeDetails := MessageText.Get(I) as TJSONObject;
MsgDetail := NodeDetails.Get('query').JSONValue as TJSONString;
Item.Caption := MsgDetail.Value;
end;
实际上,此功能适用于Twitter API的其他JSON结果。它不适用于这一结果。
答案 0 :(得分:6)
JSONObject := TJSONObject.ParseJSONValue(TEncoding.UTF8.GetBytes(JSON), 0) as TJSONObject;
JSON的根是数组,而不是对象。因此错误。
您需要将ParseJSONValue()
的返回值转换为TJSONArray
而不是TJSONObject
,然后您可以访问数组中的第一个元素并读取其trends
值。您已经拥有解析数组的代码,因此您清楚地知道如何执行此操作。
如果您不清楚对象和数组的JSON术语,请阅读JSON spec。
答案 1 :(得分:0)
正如David指出的那样,问题在于您的代码假定JSON文本是一个对象,在这种情况下,它是一个数组。
在代码不知道特定JSON容器是对象还是数组的情况下,my alternative JSON library提供了一种处理方法,通过提供专门用于处理JSON的TJSONText类,您不一定知道(或关心)所涉及的JSON是对象还是数组。
在您的情况下,生成的代码将类似于:
response := TJSONText.CreateFromUTF8(JSON);
case response.ValueType of
jsArray : MessageText := response.AsArray[0].AsObject['trends'].AsArray;
jsObject : MessageText := NIL; // or as appropriate to extract "trends" from a single object response
end;
if Assigned(MessageText) then
begin
.. etc etc
end;