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

如何在Delphi中正确解析Shopify的JSON响应(含空值处理)

解决Shopify JSON解析的Delphi代码优化问题

问题背景

需要解析Shopify返回的JSON响应,提取其中id和price字段,但存在以下难点:

  • variant[n]是动态命名的键(如variant0、variant1),并非JSON数组,数量未知
  • 部分variant[n]下的productVariant为null,原代码遇到null会触发异常,导致循环提前终止

优化方案

1. 替换异常捕获,主动检查节点状态

原代码依赖try-except捕获异常判断节点存在性,不仅性能差,还无法区分“节点不存在”和“节点为null”的情况。改为逐层检查:

  • 先获取data对象
  • 检查目标variant节点是否存在
  • 若存在,再确认productVariant不为null
  • 最后安全提取id和price

2. 两种可靠的遍历方式

方式一:按序号循环检查(适配连续命名场景)

适合确认variant是连续序号命名的情况,循环检查每个variant[i],直到找不到为止。

方式二:遍历data所有属性(适配任意命名场景)

直接遍历data对象的所有键,筛选出以variant开头的键,无需依赖序号连续性,兼容性更强。

优化后的代码示例

方式一:按序号循环检查

procedure TfrmMain.Button20Click(Sender: TObject);
var
  JsonValue: TJSONValue;
  DataObj: TJSONObject;
  VariantObj: TJSONObject;
  ProductVarObj: TJSONValue;
  i: Integer;
  resp: string;
  id, price: string;
begin
  resp := mmInputs.Lines.Text;
  JsonValue := TJSONObject.ParseJSONValue(resp);
  try
    if JsonValue is TJSONObject then
    begin
      DataObj := JsonValue.GetValue<TJSONObject>('data');
      if Assigned(DataObj) then
      begin
        i := 0;
        while True do
        begin
          // 检查当前variant[i]是否存在
          VariantObj := DataObj.GetValue<TJSONObject>('variant' + IntToStr(i));
          if not Assigned(VariantObj) then
            Break; // 无更多variant,退出循环

          // 检查productVariant是否非空
          ProductVarObj := VariantObj.GetValue('productVariant');
          if Assigned(ProductVarObj) and (ProductVarObj.ValueType <> jvtNull) then
          begin
            id := ProductVarObj.GetValue<string>('id');
            price := ProductVarObj.GetValue<string>('price');
            Memo1.Lines.Add('variant' + IntToStr(i) + ' id=' + id + ' price=' + price);
          end;

          Inc(i);
        end;
      end;

      // 提取剩余请求点数
      Memo1.Lines.Add('pointsRemaining:' + JsonValue.GetValue<string>('extensions.cost.throttleStatus.currentlyAvailable'));
    end;
  finally
    JsonValue.Free;
  end;
end;

方式二:遍历data的所有属性

procedure TfrmMain.Button20Click(Sender: TObject);
var
  JsonValue: TJSONValue;
  DataObj: TJSONObject;
  Pair: TJSONPair;
  VariantObj: TJSONObject;
  ProductVarObj: TJSONValue;
  resp: string;
  id, price: string;
begin
  resp := mmInputs.Lines.Text;
  JsonValue := TJSONObject.ParseJSONValue(resp);
  try
    if JsonValue is TJSONObject then
    begin
      DataObj := JsonValue.GetValue<TJSONObject>('data');
      if Assigned(DataObj) then
      begin
        // 遍历data下所有键值对
        for Pair in DataObj do
        begin
          // 筛选variant开头的键
          if StartsText('variant', Pair.JsonString.Value) then
          begin
            VariantObj := Pair.JsonValue as TJSONObject;
            if Assigned(VariantObj) then
            begin
              ProductVarObj := VariantObj.GetValue('productVariant');
              if Assigned(ProductVarObj) and (ProductVarObj.ValueType <> jvtNull) then
              begin
                id := ProductVarObj.GetValue<string>('id');
                price := ProductVarObj.GetValue<string>('price');
                Memo1.Lines.Add(Pair.JsonString.Value + ' id=' + id + ' price=' + price);
              end;
            end;
          end;
        end;
      end;

      Memo1.Lines.Add('pointsRemaining:' + JsonValue.GetValue<string>('extensions.cost.throttleStatus.currentlyAvailable'));
    end;
  finally
    JsonValue.Free;
  end;
end;

关键改进点

  • 主动检查节点存在性和非空状态,替代异常捕获,提升性能和准确性
  • 两种遍历方式覆盖不同场景:连续序号用方式一,任意命名用方式二
  • 避免因单个null节点导致整个循环终止

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 23:00:38