You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用TJSONIterator.Next正确填充TListView?解决首项缺失问题

解决TJSONIterator填充TListView时第一项数据缺失的问题

你当前的代码存在几处逻辑错误,导致第一项数据缺失,同时整体解析逻辑混乱,以下是问题分析和修正方案:

问题分析

  1. 初始化阶段多余的NObjJSON := LIterator.AsInteger;完全无意义,此时迭代器尚未定位到有效数值,这行代码会干扰迭代器的初始状态。
  2. 遇到StartObject/StartArray后立即调用LIterator.Recurse+LIterator.Next,直接跳过了第一个元素的起始标记,导致第一个JSON对象的解析被跳过。
  3. 错误地将每个JSON键值对作为ListView的单独项,而非将success数组中的每个完整对象对应一个ListView项,且内部的for循环逻辑完全错误,重复赋值同一个Item。

原始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
}

修正后的代码

var
  LStringReader: TStreamReader;
  LJsonTextReader: TJsonTextReader;
  LIterator: TJSONIterator;
  oItem: TListViewItem;
  ObjIndex: Integer;
  CurrentSymbol, CurrentExchange: string;
begin
  LStringReader := TStreamReader.Create('../../Data.json', TEncoding.UTF8, True);
  try
    LJsonTextReader := TJsonTextReader.Create(LStringReader);
    try
      LIterator := TJSONIterator.Create(LJsonTextReader);
      try
        ListView1.Items.Clear;
        ListView1.BeginUpdate;
        try
          ObjIndex := 0;
          // 定位到success数组
          while LIterator.Next do
          begin
            if LIterator.Key = 'success' then
            begin
              if LIterator.&Type = TJsonToken.StartArray then
              begin
                // 进入success数组
                LIterator.Recurse;
                // 遍历数组中的每个对象
                while LIterator.Next do
                begin
                  if LIterator.&Type = TJsonToken.StartObject then
                  begin
                    Inc(ObjIndex);
                    CurrentSymbol := '';
                    CurrentExchange := '';
                    // 进入当前对象,提取字段
                    LIterator.Recurse;
                    while LIterator.Next do
                    begin
                      if LIterator.Key = 'symbol' then
                        CurrentSymbol := LIterator.AsValue.ToString
                      else if LIterator.Key = 'exchange' then
                        CurrentExchange := LIterator.AsValue.ToString;
                    end;
                    LIterator.Return; // 退出当前对象

                    // 创建ListView项并赋值
                    oItem := ListView1.Items.Add;
                    oItem.Text := 'Object #' + ObjIndex.ToString + ' ' + CurrentSymbol;
                    oItem.Detail := 'Exchange: ' + CurrentExchange;
                  end;
                end;
                LIterator.Return; // 退出success数组
                Break; // 找到success数组后无需继续遍历外层
              end;
            end;
          end;
        finally
          ListView1.EndUpdate;
        end;
      finally
        LIterator.Free;
      end;
    finally
      LJsonTextReader.Free;
    end;
  finally
    LStringReader.Free;
  end;
end;

代码说明

  • 先定位到success数组,避免遍历无关的JSON字段(如event、status)
  • 逐个遍历数组中的每个对象,为每个对象创建一个ListView项
  • 提取对象中的关键字段(如symbol、exchange)整合到Item的Text和Detail中
  • 严格控制迭代器的Recurse和Return,确保每次进入/退出对象/数组的逻辑正确,不会跳过元素

内容的提问来源于stack exchange,提问作者Ody Light

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 06:05:49