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

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;

关键注意点

  1. 原代码的finally块没有释放vJson,这会导致内存泄漏,一定要记得调用vJson.Free。
  2. 对于嵌套的JSON对象,必须先把JsonValue转换成TJSONObject类型,才能访问它内部的字段。
  3. 使用GetValue<T>方法可以直接把JSON值转换成对应的数据类型,比手动处理更方便。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 23:27:36