delphifiremonkeytlistview

How to fill TListView with TJSONIterator.Next?


I have an app with a TListView and I want to populate data from JSON inside its Items by using TJSONIterator.Next(). The code I use displays the results I want, except for the first one.

How can I parse these JSON objects correctly, what am I doing wrong?

image

Data: 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
}

Code app:

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;

Solution

  • After all, i found the correct solution:*

    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 is used to count the number of objects inside array and it returns 4. You can use a simple integer (I) and replace "for NObjJSON := 0 to ListView1.ItemCount -1 do" by for I := 0 to ListView1.ItemCount -1 do but the number of objects will return 0.