如何使用TJSONIterator.Next填充TListView?

3

我有一个带有 TListView 的应用程序,我想通过使用 TJSONIterator.Next() 在其 Items 中填充来自 JSON 的数据。我使用的代码显示了我想要的结果,除了第一个。

我该如何正确解析这些 JSON 对象,我做错了什么?

image

数据:Data.json

{
  "event":"subscribe-status",
  "status":"ok",
  "success":[
    {
      "symbol":"EUR/USD",
      "exchange":"PHYSICAL CURRENCY",
      "mic_code":"PHYSICAL CURRENCY",
      "country":"",
      "type":"Physical Currency"
    },
    {
      "symbol":"USD/JPY",
      "exchange":"PHYSICAL CURRENCY",
      "mic_code":"PHYSICAL CURRENCY",
      "country":"",
      "type":"Physical Currency"
    },
    {
      "symbol":"BTC/USD",
      "exchange":"Coinbase Pro",
      "mic_code":"Coinbase Pro",
      "country":"",
      "type":"Digital Currency"
    },
    {
      "symbol":"ETH/BTC",
      "exchange":"Huobi",
      "mic_code":"Huobi",
      "country":"",
      "type":"Digital Currency"
    }
  ],
  "fails":null
}

编写应用程序:

LStringReader := TStreamReader.Create('../../Data.json', TEncoding.UTF8, True);
LJsonTextReader := TJsonTextReader.Create(LStringReader);
LIterator := TJSONIterator.Create(LJsonTextReader);
NObjJSON := LIterator.AsInteger;
    
ListView1.Items.Clear;
ListView1.BeginUpdate;
try
  while True do
  begin
    while LIterator.Next do
    begin
      if LIterator.&Type in [TJsonToken.StartObject, TJsonToken.StartArray] then
      begin
        LIterator.Recurse;
        LIterator.Next;
        oItem := ListView1.Items.Add;
        for NObjJSON := 0 to ListView1.ItemCount -1 do
        begin
          oItem.Text := 'Object #' + NObjJSON.ToString + ' ' + LIterator.AsValue.ToString;
          oItem.Detail := 'Key:' +LIterator.Key;
        end
      end;
    end;
    if LIterator.InRecurse then
      LIterator.Return
    else
      Break;
  end;
finally
  ListView1.EndUpdate;
  LIterator.Free;
  LJsonTextReader.Free;
  lStringReader.Free;
  Memo1.Lines.Text := NObjJSON.ToString;
end;
2个回答

3
在编程中,将以下代码添加到循环的开头,以准备进入数组:

添加此递归/下一个

while LIterator.Next do
begin
  if LIterator.&Type = TJsonToken.StartArray then
  begin
    LIterator.Recurse;
    LIterator.Next;
  end;

您可以在文档中查看此示例:https://docwiki.embarcadero.com/CodeExamples/Sydney/en/RTL.JSONIterator

以下代码更易于阅读:

procedure TFormX.LoadJSON;
const
  cValue = 'symbol';
var
  LValue: TJSONValue;
  LArray: TJSONArray;
  i: integer;
  oItem: TListViewItem;
begin
  LValue := TJSONObject.ParseJSONValue('{json}');

  LArray := LValue.FindValue('success') as TJSONArray;

  if Assigned(LArray) then
  begin
    for i := 0 to LArray.Count - 1 do
    begin
      oItem := ListView1.Items.Add;

      oItem.Text := 'Object #' + i.ToString + ' ' + LArray.Items[i].GetValue<string>(cValue);
      oItem.Detail := 'Key:' + cValue;
    end;
  end;
end;

使用TJSONObject更容易,没错!但问题是关于TJSONIterator的。 - Ody Light
这就是为什么我首先使用TJSONIterator进行了回答。 - Bosshoss
抱歉耽搁了这么久,@Bosshoss,我尝试过了,但对我来说不起作用,可能是我漏掉了什么! - Ody Light
是的,我认为你漏掉了一些东西。 - Bosshoss

0

最终,我找到了正确的解决方案:*

var
  LIterator: TJSONIterator;
  LJsonTextReader: TJsonTextReader;
  LStringReader: TStreamReader;
  NObjJSON: Integer;
begin
  LStringReader := TStreamReader.Create('../../Data.json', TEncoding.UTF8, True);
  LJsonTextReader := TJsonTextReader.Create(LStringReader);
  LIterator := TJSONIterator.Create(LJsonTextReader);
  NObjJSON := LIterator.AsInteger;

  ListView1.Items.Clear;
  ListView1.BeginUpdate;
  try
    while True do
    begin
      while LIterator.Next do
      begin
        if LIterator.&Type in [TJsonToken.StartObject, TJsonToken.StartArray] then
        begin
          Memo1.Lines.Add(LIterator.Key);
          LIterator.Recurse;
        end
        else if LIterator.Path = 'success['+NObjJSON.ToString+'].symbol' then
        begin
            Memo1.Lines.Add(LIterator.AsValue.ToString);
            oItem := ListView1.Items.Add;
            for NObjJSON := 0 to ListView1.ItemCount -1 do
              oItem.Text := 'Object #' + NObjJSON.ToString + ' ' + LIterator.AsValue.ToString;
        end
      end;
      if LIterator.InRecurse then
        LIterator.Return
      else
        Break;
    end;
  finally
    ListView1.EndUpdate;
    LIterator.Free;
    LJsonTextReader.Free;
    LStringReader.Free;
  end;
end;

enter image description here enter image description here

NObjJSON 用于计算数组中对象的数量,并返回4。 您可以使用一个简单的整数(I),并将“for NObjJSON := 0 to ListView1.ItemCount -1 do”替换为for I := 0 to ListView1.ItemCount -1 do,但对象的数量将返回0。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接