Delphi「Invalid class type cast」错误解决:统计JSON数组元素数
解决Delphi中JSON数组统计的「Invalid class type cast」错误
错误原因
你遇到的「Invalid class type cast」错误,核心问题是接口返回的JSON根结构是对象(TJSONObject),而非数组(TJSONArray)。你的JSONArrayCovertCnt函数直接将整个JSON字符串解析后强制转为TJSONArray,这种类型转换必然失败,触发错误。
解决方案
1. 修复JSONArrayCovertCnt函数
正确逻辑是先解析根对象,再从中提取data字段对应的数组:
function JSONArrayCovertCnt(usJSON: string): integer; var JSONObj : TJSONObject; JSONArray : TJSONArray; begin usJson := StringReplace(usJSON,'\"','"',[rfReplaceAll]); // 先解析为根对象 JSONObj := TJSONObject.ParseJSONValue(usJSON) as TJSONObject; try if Assigned(JSONObj) then begin // 取出data字段对应的数组 JSONArray := JSONObj.GetValue<TJSONArray>('data'); Result := IfThen(Assigned(JSONArray), JSONArray.Count, 0); end else Result := 0; finally JSONObj.Free; // 释放对象,避免内存泄漏 end; end;
2. 优化主函数代码(避免重复解析+修复循环越界)
你在Button1Click中已经解析过一次JSON,没必要重复调用函数解析字符串。直接从已有的JSONValue中提取数组更高效,同时修复硬编码循环范围的问题:
procedure TForm1.Button1Click(Sender: TObject); var stream: TStringStream; idHttpObj: TIdHTTP; JSONValue : TJSONValue; i : integer; JSONArray : TJSONArray; resultCnt : integer; // 重命名变量,避开关键字冲突 begin stream := TStringStream.Create('', TEncoding.UTF8); try idHttpObj := TIdHTTP.Create(nil); try idHttpObj.Get(Url, stream); finally idHttpObj.Free; end; JSONValue := TJSONObject.ParseJSONValue(stream.DataString); try memo1.Clear; if JSONValue is TJSONObject then begin // 获取data数组 JSONArray := (JSONValue as TJSONObject).GetValue<TJSONArray>('data'); if Assigned(JSONArray) then begin // 动态循环数组所有元素,避免硬编码导致越界 for i := 0 to JSONArray.Count - 1 do begin Memo1.Lines.Add('year: ' + JSONValue.GetValue<string>('data['+i.ToString+'].year') + '년'); Memo1.Lines.Add('hshld: ' + JSONValue.GetValue<string>('data['+i.ToString+'].hshld') + ' 가구'); Memo1.Lines.Add('popltn: ' + JSONValue.GetValue<string>('data['+i.ToString+'].popltn_sm') + '명'); Memo1.Lines.Add('popltn_male: ' + JSONValue.GetValue<string>('data['+i.ToString+'].popltn_male') + '명'); Memo1.Lines.Add('popltn_female: ' + JSONValue.GetValue<string>('data['+i.ToString+'].popltn_female') + '명'); Memo1.Lines.Add('hshld_avrgpopltn: ' + JSONValue.GetValue<string>('data['+i.ToString+'].hshld_avrgpopltn') + '명'); Memo1.Lines.Add('────────────────────────────────────'); end; resultCnt := JSONArray.Count; end else resultCnt := 0; // 输出其他响应字段 Memo1.Lines.Add('resultCode: ' + JSONValue.GetValue<string>('resultCode')); Memo1.Lines.Add('resultMsg: ' + JSONValue.GetValue<string>('resultMsg')); Memo1.Lines.Add('numOfRows : ' + JSONValue.GetValue<string>('numOfRows')); Memo1.Lines.Add('totalcount: ' + JSONValue.GetValue<string>('totalCount')); edit1.Text := IntToStr(resultCnt); end; finally JSONValue.Free; // 释放解析后的JSON对象 end; finally stream.Free; end; end;
额外注意事项
- 内存管理:所有通过
ParseJSONValue创建的JSON对象必须手动调用Free释放,防止内存泄漏。 - 空值检查:访问数组或字段前,务必用
Assigned判断是否为空,避免空指针异常。 - 循环逻辑:不要硬编码循环范围,利用数组
Count动态适配返回结果长度。
内容的提问来源于stack exchange,提问作者SangPro
相关产品推荐
相关产品推荐

