Json解析";无效的类类型转换“;问题[Delphi XE7]

Json解析";无效的类类型转换“;问题[Delphi XE7],json,delphi,parsing,delphi-xe7,Json,Delphi,Parsing,Delphi Xe7,我正在尝试使用DelphiXe7解析来自TwitterAPI的JSON结果。我得到了一个“无效的类类型转换”错误,但是我用一个在线验证器检查了JSON,结果没有问题 以下是JSON结果: [ { “趋势”: [ { “名称”:“#一方当事人”, “url”:”http://twitter.com/search?q=%23OneDirectionIsOverParty", “升级内容”:空, “查询”:“%23OneDirectionOverparty”, “推特音量”:410022 }, { “

我正在尝试使用DelphiXe7解析来自TwitterAPI的JSON结果。我得到了一个“无效的类类型转换”错误,但是我用一个在线验证器检查了JSON,结果没有问题

以下是JSON结果:

[
{
“趋势”:
[
{
“名称”:“#一方当事人”,
“url”:”http://twitter.com/search?q=%23OneDirectionIsOverParty",
“升级内容”:空,
“查询”:“%23OneDirectionOverparty”,
“推特音量”:410022
},
{
“姓名”:“黑暗骑士”,
“url”:”http://twitter.com/search?q=%23TheDarkKnight",
“升级内容”:空,
“查询”:“%23TheDarkKnight”,
“推特音量”:空
},
{
“名称”:“QuintaComOClubeSdv”,
“url”:”http://twitter.com/search?q=%23QuintaComOClubeSdv",
“升级内容”:空,
“查询”:“%23QuintaComOClubeSdv”,
“推特音量”:23756
}
],
“作为的”:“2016-07-21T20:14:13Z”,
“创建时间”:“2016-07-21T20:08:31Z”,
“地点”:
[
{
“名称”:“全球”,
“悲哀”: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;
实际上,该函数与来自TwitterAPI的其他JSON结果一起工作。它不仅仅是在这个结果上工作

JSONObject := TJSONObject.ParseJSONValue(TEncoding.UTF8.GetBytes(JSON), 0) as TJSONObject;
JSON的根是数组,而不是对象。因此出现了错误

您需要将
ParseJSONValue()
的返回值强制转换为
TJSONArray
,而不是
TJSONObject
,然后您可以访问数组中的第一个元素并读取其
trends
值。您已经有了解析数组的代码,因此您清楚地知道如何进行解析

如果您不清楚对象和数组的JSON术语,请阅读

JSON的根是数组,而不是对象。因此出现了错误

您需要将
ParseJSONValue()
的返回值强制转换为
TJSONArray
,而不是
TJSONObject
,然后您可以访问数组中的第一个元素并读取其
trends
值。您已经有了解析数组的代码,因此您清楚地知道如何进行解析


如果您不清楚object和array的JSON术语,请阅读。

正如David所指出的,问题是您的代码假设JSON文本是一个对象,而在这种特定情况下,它是一个数组

在代码不知道特定JSON容器是对象还是数组的情况下,通过提供一个TJSONText类专门用于处理JSON,而您不一定知道(或关心)所涉及的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;

正如David所指出的,问题在于您的代码假设JSON文本是一个对象,而在本例中它是一个数组

在代码不知道特定JSON容器是对象还是数组的情况下,通过提供一个TJSONText类专门用于处理JSON,而您不一定知道(或关心)所涉及的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;

调试器在哪一行中断?您已经详细介绍了代码了吗?Hey@jerrydoge“JSONObject:=TJSONObject.ParseJSONValue(TEncoding.UTF8.GetBytes(JSON),0)作为TJSONObject;“我不熟悉这个特定的JSON库,但我猜您应该将其作为数组而不是对象进行解析——因为根元素是数组。事实上,您的代码似乎与此JSON数据完全不匹配。此外,代码正在泄漏
ParseJSONValue()
返回的
TJSONValue
。当你使用完它后,你需要
释放它。调试器在哪一行中断?您已经详细介绍了代码了吗?Hey@jerrydoge“JSONObject:=TJSONObject.ParseJSONValue(TEncoding.UTF8.GetBytes(JSON),0)作为TJSONObject;“我不熟悉这个特定的JSON库,但我猜您应该将其作为数组而不是对象进行解析——因为根元素是数组。事实上,您的代码似乎与此JSON数据完全不匹配。此外,代码正在泄漏
ParseJSONValue()
返回的
TJSONValue
。当你使用完它后,你需要
释放它。因为同样的代码被用来解析Twitter的多个结果,其中一些结果以对象开头,一些结果以数组开头,你可以保存
ParseJSONValue()的返回值
转换为本地
TJSONValue
变量,然后使用
is
操作符检查它是否真的是
TJSONObject
TJSONArray
。由于使用相同的代码解析Twitter的多个结果,其中一些以对象开头,另一些以数组开头,您可以将
ParseJSONValue()
的返回值保存到本地
TJSONValue
变量,然后使用
is
操作符在强制转换之前检查它是否确实是
TJSONObject
TJSONArray