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

Delphi如何解析URL返回的JSON数组并将数据展示到ListView

问题排查与修正方案

现有代码核心错误点

  • 类型转换错误:你请求返回的JSON根结构是数组,不是对象,你直接将解析得到的TJsonValue强制转为TJSONObject会直接触发类型转换异常,而你把所有异常都吞了没有任何提示,所以看起来点击按钮没反应
  • 无效的冗余操作:你不需要自己手动创建TJSONArray和TJSONPair,接口返回的内容已经是完整可直接读取的JSON数组,额外创建的逻辑完全多余,且你声明的js: TJsonObject变量没有初始化就调用AddPair方法,会触发空指针异常
  • 异常处理缺失:两处try except块都只捕获异常但没有任何提示逻辑,运行出错你完全感知不到,无法定位问题
  • ListView更新逻辑不合理:每次加一个item就调用一次BeginUpdate/EndUpdate,性能极低,应该放在循环外层统一调用

正确实现方案

你不需要额外创建JSON数组存储,接口返回的内容解析后直接读取即可,修正后的代码如下:

1. 先修正网络请求函数(补充编码和异常提示)

uses
  IdHTTP, IdSSLOpenSSL, System.JSON, System.SysUtils, FMX.ListView.Types; 
  // 注意对应你用的是VCL还是FMX,自行调整uses引用

function GetURLAsString(const aurl: string): string;
var
  IdHTTP1 : TIdHTTP;
  SSLHandler: TIdSSLIOHandlerSocketOpenSSL;
begin
  IdHTTP1 := TIdHTTP.Create(nil);
  SSLHandler := TIdSSLIOHandlerSocketOpenSSL.Create(IdHTTP1);
  try
    IdHTTP1.IOHandler := SSLHandler;
    IdHTTP1.Request.ContentType := 'application/json';
    IdHTTP1.Request.Accept := 'application/json';
    IdHTTP1.ConnectTimeout := 10000;
    IdHTTP1.ReadTimeout := 10000;
    Result := IdHTTP1.Get(aurl);
  finally
    IdHTTP1.Free;
  end;
end;

2. 修正按钮点击事件逻辑

procedure TForm4.Button1Click(Sender: TObject);
var
  jsv : TJsonValue;
  jsa : TJsonArray;
  itemObj : TJSONObject;
  data : string;
  i : integer;
  LItem : TListViewItem;
  dateVal, quantityVal, unitPriceVal: string;
begin
  // 先清空ListView旧数据
  ListView1.Items.Clear;
  try
    data := GetURLAsString('替换为你的实际接口地址');
    if Trim(data) = '' then
    begin
      ShowMessage('接口返回空数据');
      Exit;
    end;
  except
    on E: Exception do
    begin
      ShowMessage('网络请求出错:' + E.Message);
      Exit;
    end;
  end;

  try
    jsv := TJSONObject.ParseJSONValue(data);
    if not Assigned(jsv) then
    begin
      ShowMessage('JSON解析失败');
      Exit;
    end;
    try
      // 根是数组,直接转TJSONArray
      if not jsv.InheritsFrom(TJSONArray) then
      begin
        ShowMessage('返回JSON结构不是数组');
        Exit;
      end;
      jsa := TJSONArray(jsv);

      // 批量更新ListView,放循环外层
      ListView1.BeginUpdate;
      try
        for I  := 0 to jsa.Size - 1 do
        begin
          if not jsa.Get(i).InheritsFrom(TJSONObject) then Continue;
          itemObj := TJSONObject(jsa.Get(i));
          
          // 直接读取三个字段值
          dateVal := itemObj.GetValue<string>('DATE', '');
          quantityVal := itemObj.GetValue<string>('QUANTITY', '');
          unitPriceVal := itemObj.GetValue<string>('UNITPRICE', '');

          // 添加到ListView
          LItem := ListView1.Items.Add;
          LItem.Text := dateVal;
          // 如果要显示另外两个字段,用Detail或者子项,比如:
          LItem.Detail := Format('数量:%s,单价:%s', [quantityVal, unitPriceVal]);
        end;
      finally
        ListView1.EndUpdate;
      end;
    finally
      jsv.Free;
    end;
  except
    on E: Exception do
    begin
      ShowMessage('数据处理出错:' + E.Message);
      Exit;
    end;
  end;
end;

补充注意事项

  • 如果你的程序是Windows平台,需要把OpenSSL的两个库libeay32.dll和ssleay32.dll放到程序运行目录,否则HTTPS请求会失败
  • 如果是VCL的ListView,添加项的逻辑和FMX略有区别,自行调整即可
  • 如果你要存到本地后续使用,可以声明一个全局的TJSONArray变量,解析后赋值给它,后续直接读取即可,不需要额外转换

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 15:36:02