【问题标题】:Json Parse "Invalid class typecast" issue. [Delphi XE7]Json Parse“无效的类类型转换”问题。 [德尔福XE7]
【发布时间】:2016-07-21 20:26:45
【问题描述】:

我正在尝试使用 Delphi XE7 解析来自 Twitter API 的 JSON 结果。我收到“Invalid class typecast”错误,但我使用在线验证器检查 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 结果。它不仅对这一个结果起作用。

【问题讨论】:

  • 调试器在哪一行中断?你已经通过代码了吗?
  • 嘿@JerryDodge "JSONObject := TJSONObject.ParseJSONValue(TEncoding.UTF8.GetBytes(JSON), 0) as TJSONObject;"
  • 我不熟悉这个特定的 JSON 库,但我猜你应该将它解析为数组而不是对象 - 因为根元素是一个数组。事实上,您的代码似乎与此 JSON 数据完全不匹配。
  • 另外,代码泄露了ParseJSONValue() 返回的TJSONValue。使用完毕后需要Free

标签: json delphi parsing delphi-xe7


【解决方案1】:
JSONObject := TJSONObject.ParseJSONValue(TEncoding.UTF8.GetBytes(JSON), 0) as TJSONObject;

JSON 的根是一个数组,而不是一个对象。因此错误。

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

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

【讨论】:

  • 由于使用相同的代码来解析 Twitter 的多个结果,其中一些以 object 开头,一些以 array 开头,您可以将ParseJSONValue() 的返回值保存到本地TJSONValue 变量中,然后在转换之前使用is 运算符检查它是否真的是TJSONObjectTJSONArray
【解决方案2】:

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

在代码不知道特定 JSON 容器是对象还是数组的情况下,my alternative JSON library 提供了一种处理此问题的方法,即提供一个 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;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-05
    • 2020-04-24
    • 2014-11-01
    • 1970-01-01
    • 2014-07-08
    相关资源
    最近更新 更多