如何在Delphi中遍历包含多条记录的JSON数据
问题分析与解决方案
错误根源
你遇到的Invalid class typecast错误,核心原因是返回的JSON根节点是对象(TJSONObject),而非数组(TJSONArray)。原代码强行将根节点转为TJSONArray,触发了类型转换错误。
看你的JSON结构,最外层是包含Accounts键的对象,Accounts对应的值才是需要遍历的账户数组:
{ "Accounts": [/* 账户数组 */] }
修正后的代码
以下是修复后的完整代码,可直接遍历账户并提取字段:
try xeroRequest.Execute; if Assigned(xeroResponse.JSONValue) then begin // 根节点是TJSONObject,直接转换 jRootObj := xeroResponse.JSONValue as TJSONObject; try // 取出Accounts对应的数组 jAccountsArray := jRootObj.GetValue('Accounts') as TJSONArray; if Assigned(jAccountsArray) then begin idx := 1; // 遍历每个账户对象 for arrElement in jAccountsArray do begin jAccountObj := arrElement as TJSONObject; // 提取AccountID if jAccountObj.TryGetValue('AccountID', AcctId) then begin memoJson.Lines.Add(Format('%d: %s', [idx, AcctId])); end; // 提取其他字段示例 var AcctCode, AcctName: string; var EnablePayments: Boolean; jAccountObj.TryGetValue('Code', AcctCode); jAccountObj.TryGetValue('Name', AcctName); jAccountObj.TryGetValue('EnablePaymentsToAccount', EnablePayments); // 此处可添加数据库插入逻辑,例如: // MyQuery.ParamByName('AccountID').AsString := AcctId; // MyQuery.ParamByName('Code').AsString := AcctCode; // MyQuery.ExecSQL; inc(idx); end; end; finally // 注意:若xeroResponse.JSONValue由Xero SDK管理内存,请勿手动Free,避免内存错误 // jRootObj.Free; end; end; except on E:Exception do ShowMessage('Error: ' + xeroResponse.ErrorMessage + ' - ' + E.Message); end;
关键注意事项
- 安全类型判断:处理JSON前用
is关键字确认节点类型,比如if xeroResponse.JSONValue is TJSONObject then,避免强制转换出错。 - 字段提取容错:优先用
TryGetValue而非直接GetValue,防止字段不存在时抛出异常。 - 内存管理:确认Xero SDK返回的
JSONValue是否由框架自行管理,不要随意调用Free,避免程序崩溃。 - 数据库插入规范:根据数据库字段类型转换提取到的值(比如布尔值转BIT/BOOLEAN类型),使用参数化查询执行插入,避免SQL注入。
内容的提问来源于stack exchange,提问作者Paul Coshott
相关产品推荐
相关产品推荐

