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
相关产品推荐
相关产品推荐

