Delphi 10.4中如何解析JSON嵌套结构里的Price字段值?
Delphi 10.4解析JSON中嵌套Price对象的正确方法
你的问题出在Price是嵌套的JSON对象,而不是字符串、数字这类简单值——原代码里直接调用JsonValue.Value只能获取简单类型的内容,对嵌套对象来说这个属性不会返回内部的键值对,自然拿不到Value和Quantity的值。
下面给你两种可行的解决方式:
方式一:直接指定键获取(适合已知JSON结构的场景)
既然你清楚JSON的结构,直接定位到Price对象,再提取里面的字段就好,代码更简洁:
var vContent: TJSONArray; vJson: TJSONObject; vContentRow: TJSONObject; vPriceObj: TJSONObject; i: Integer; begin Memo2.Lines.Clear; if Memo1.Text = '' then Exit; // 解析JSON字符串 vJson := TJSONObject(TJSONObject.ParseJSONValue(TEncoding.ASCII.GetBytes(Memo1.Text), 0)); try vContent := TJSONArray(vJson.Get('Content').JsonValue); for i := 0 to Pred(vContent.Count) do begin vContentRow := TJSONObject(vContent.Items[i]); // 先提取普通字段 Memo2.Lines.Add('Identifier: ' + vContentRow.GetValue<string>('Identifier')); Memo2.Lines.Add('Description: ' + vContentRow.GetValue<string>('Description')); Memo2.Lines.Add('GenericProductIdentifier: ' + vContentRow.GetValue<string>('GenericProductIdentifier')); Memo2.Lines.Add('ProductFamilyDescription: ' + vContentRow.GetValue<string>('ProductFamilyDescription')); Memo2.Lines.Add('LifeCycleStatus: ' + vContentRow.GetValue<string>('LifeCycleStatus')); Memo2.Lines.Add('LeadTimeWeeks: ' + vContentRow.GetValue<string>('LeadTimeWeeks')); Memo2.Lines.Add('FullBoxQty: ' + IntToStr(vContentRow.GetValue<Integer>('FullBoxQty'))); // 处理嵌套的Price对象 vPriceObj := TJSONObject(vContentRow.Get('Price').JsonValue); if Assigned(vPriceObj) then begin Memo2.Lines.Add('--- Price 详情 ---'); Memo2.Lines.Add('Value: ' + FloatToStr(vPriceObj.GetValue<Double>('Value'))); Memo2.Lines.Add('Quantity: ' + IntToStr(vPriceObj.GetValue<Integer>('Quantity'))); end; end; finally vJson.Free; // 务必释放对象,避免内存泄漏! end; end;
方式二:递归遍历所有字段(适合未知JSON结构的场景)
如果你的JSON结构可能变化,写一个递归函数自动识别值类型,处理嵌套对象/数组:
// 递归解析JSON值的辅助函数 procedure ParseJSONValue(const AName: string; AValue: TJSONValue; AMemo: TMemo); var i: Integer; vObj: TJSONObject; vArr: TJSONArray; begin if AValue is TJSONString then AMemo.Lines.Add(AName + ': ' + TJSONString(AValue).Value) else if AValue is TJSONNumber then AMemo.Lines.Add(AName + ': ' + TJSONNumber(AValue).Value) else if AValue is TJSONBool then AMemo.Lines.Add(AName + ': ' + BoolToStr(TJSONBool(AValue).Value, True)) else if AValue is TJSONObject then begin AMemo.Lines.Add(AName + ': {'); vObj := TJSONObject(AValue); for i := 0 to Pred(vObj.Count) do ParseJSONValue(' ' + vObj.Get(i).JsonString.Value, vObj.Get(i).JsonValue, AMemo); AMemo.Lines.Add('}'); end else if AValue is TJSONArray then begin AMemo.Lines.Add(AName + ': ['); vArr := TJSONArray(AValue); for i := 0 to Pred(vArr.Count) do ParseJSONValue(' 条目 ' + IntToStr(i), vArr.Items[i], AMemo); AMemo.Lines.Add(']'); end; end; // 主调用代码 var vContent: TJSONArray; vJson: TJSONObject; vContentRow: TJSONObject; i: Integer; begin Memo2.Lines.Clear; if Memo1.Text = '' then Exit; vJson := TJSONObject(TJSONObject.ParseJSONValue(TEncoding.ASCII.GetBytes(Memo1.Text), 0)); try vContent := TJSONArray(vJson.Get('Content').JsonValue); for i := 0 to Pred(vContent.Count) do begin vContentRow := TJSONObject(vContent.Items[i]); ParseJSONValue('内容行 ' + IntToStr(i), vContentRow, Memo2); end; finally vJson.Free; end; end;
关键注意点
- 原代码的
finally块没有释放vJson,这会导致内存泄漏,一定要记得调用vJson.Free。 - 对于嵌套的JSON对象,必须先把
JsonValue转换成TJSONObject类型,才能访问它内部的字段。 - 使用
GetValue<T>方法可以直接把JSON值转换成对应的数据类型,比手动处理更方便。
内容的提问来源于stack exchange,提问作者Superc
相关产品推荐
相关产品推荐

