【问题标题】:How to parse nested JSON object in Delphi XE2?如何在 Delphi XE2 中解析嵌套的 JSON 对象?
【发布时间】:2012-05-30 01:29:50
【问题描述】:

我是 JSON 新手,我手头有这个项目,需要我解析 JSON 并在 ListView 中显示它的一些内容。问题是我现在阅读的文档处理的是包含 JSON 数组的 JSON 对象,而我的案例涉及处理嵌套对象。简而言之,总结如下:我正在使用 Delphi XE2 和 DBXJSON。我将一些值发布到服务器,它会回复一个如下所示的 JSON 对象:

    {
    "products": {
        "Men's Sneakers": {
            "instock": false,
            "size": "423",
            "manufacturer": "Adidas",
            "lastcheck": "20120529"
        },
        "Purse": {
            "instock": true,
            "size": "not applicable",
            "manufacturer": "Prada",
            "lastcheck": "20120528"
        },
        "Men's Hood": {
            "instock": false,
            "size": "M",
            "manufacturer": "Generic",
            "lastcheck": "20120529"
       }
    },
   "total": 41,
   "available": 30
}

我想要实现的是解析每个项目(即钱包)并将其添加为列表视图中的标题,以及一个子项目(制造商)。我创建了一个以 JSON 字符串作为参数的过程,创建了 JSON 对象,但我不知道如何进一步解析嵌套对象。

procedure TForm1.ParseString(const AString: string);
var
  json          : TJSONObject;
  jPair         : TJSONPair;
  jValue        : TJSONValue;
  jcValue       : TJSONValue;
  l,i           : Integer;
begin
    json    := TJSONObject.ParseJSONValue(TEncoding.ASCII.GetBytes(AString),0) as TJSONObject;
  try
    //get the pair to evaluate in this case the index is 1
    jPair   := json.Get(1); 
        {further process the nested objects and adding them to the listview}
  finally
     json.Free;
  end;
end;

任何建议将不胜感激。花了很长时间试图在 Delphi 中了解 JSON 的来龙去脉,但无济于事。

谢谢, 斯芬克斯

【问题讨论】:

    标签: json delphi nested delphi-xe2


    【解决方案1】:

    试试这个示例

    {$APPTYPE CONSOLE}
    
    {$R *.res}
    
    uses
      DBXJSON,
      System.SysUtils;
    
    
    Const
    StrJson=
    '{'+
    '    "products": {'+
    '        "Men''s Sneakers": {'+
    '            "instock": false,'+
    '            "size": "423",'+
    '            "manufacturer": "Adidas",'+
    '            "lastcheck": "20120529"'+
    '        },'+
    '        "Purse": {'+
    '            "instock": true,'+
    '            "size": "not applicable",'+
    '            "manufacturer": "Prada",'+
    '            "lastcheck": "20120528"'+
    '        },'+
    '        "Men''s Hood": {'+
    '            "instock": false,'+
    '            "size": "M",'+
    '            "manufacturer": "Generic",'+
    '            "lastcheck": "20120529"'+
    '        }'+
    '    },'+
    '    "total": 41,'+
    '    "available": 30'+
    '}';
    
    procedure ParseJson;
    var
      LJsonObj  : TJSONObject;
      LJPair    : TJSONPair;
      LProducts : TJSONValue;
      LProduct  : TJSONValue;
      LItem     : TJSONValue;
      LIndex    : Integer;
      LSize     : Integer;
    begin
        LJsonObj    := TJSONObject.ParseJSONValue(TEncoding.ASCII.GetBytes(StrJson),0) as TJSONObject;
      try
         LProducts:=LJsonObj.Get('products').JsonValue;
         LSize:=TJSONArray(LProducts).Size;
         for LIndex:=0 to LSize-1 do
         begin
          LProduct := TJSONArray(LProducts).Get(LIndex);
          LJPair   := TJSONPair(LProduct);
          Writeln(Format('Product Name %s',[LJPair.JsonString.Value]));
            for LItem in TJSONArray(LJPair.JsonValue) do
            begin
               if TJSONPair(LItem).JsonValue is TJSONFalse then
                Writeln(Format('  %s : %s',[TJSONPair(LItem).JsonString.Value, 'false']))
               else
               if TJSONPair(LItem).JsonValue is TJSONTrue then
                Writeln(Format('  %s : %s',[TJSONPair(LItem).JsonString.Value, 'true']))
               else
                Writeln(Format('  %s : %s',[TJSONPair(LItem).JsonString.Value, TJSONPair(LItem).JsonValue.Value]));
            end;
         end;
      finally
         LJsonObj.Free;
      end;
    end;
    
    begin
      try
        ParseJson;
      except
        on E: Exception do
          Writeln(E.ClassName, ': ', E.Message);
      end;
      Readln;
    end.
    

    这将返回

    Product Name Men's Sneakers
      instock : false
      size : 423
      manufacturer : Adidas
      lastcheck : 20120529
    Product Name Purse
      instock : true
      size : not applicable
      manufacturer : Prada
      lastcheck : 20120528
    Product Name Men's Hood
      instock : false
      size : M
      manufacturer : Generic
      lastcheck : 20120529
    

    【讨论】:

    • 非常感谢。这就是我需要的,RRUZ。你的代码就像一个魅力。
    • 我不明白什么是pair,什么是value。也可以将 pair 转换为数组,但不能使用 'as'。我的意思是,TJSONArray(pair) 没问题,但是 (pair as TJSONArray) 产生异常。
    【解决方案2】:

    This site 更详细地描述了TJSONValue 类型。如果您的数据是一个对象,它将具有TJSONObject 类型,因此请检查其 API 以了解如何继续。

    我相信您首先需要它来迭代它的对(如果您不知道键名,请使用GetEnumerator,否则只需使用重载的Get - 传递字符串而不是数字)。对于每一对,键将是一个简单的字符串(类型TJSONString),值可以是任何TJSONValue。重复直到你到达树叶。

    例子:

    products   := jPair.Get('products');
    purse      := products.GetJsonValue().Get('Purse');
    purseManuf := purse.GetJsonValue().Get('manufacturer');
    ...
    

    或者如果您不知道产品是什么:

    products   := jPair.Get('products');
    for prodPair in products.GetEnumerator() do
    begin
        prodName := prodPair.GetJsonString();
        prodObj  := prodPair.GetJsonValue();
        ...
    

    【讨论】:

    • 你好。感谢您为我指明正确的方向。您的回答完善了@RRUZ 提供的答案。
    • 死链接... :-(
    【解决方案3】:

    This blog post 展示了一种非常现代且简单的 JSON 转换方法:

    uses REST.JSON; // Also new System.JSON
    procedure TForm1.Button1Click(Sender: TObject);
    
    var
      Foo: TFoo;
    
    begin
      Foo := TFoo.Create;
    
      try
        Foo.Foo := 'Hello World';
        Foo.Fee := 42;
        Memo1.Lines.Text := TJson.ObjectToJsonString(Foo);
      finally
        Foo.Free;
      end;
    
      Foo := TJson.JsonToObject<TFoo>(Memo1.Lines.Text);
    
      try
        Foo.Fee := 100;
        Memo1.Lines.Add(TJson.ObjectToJsonString(Foo));
      finally
        Foo.Free;
      end;
    end;
    

    【讨论】:

    • 但是 TFoo 不包含任何子对象。
    • 如果该对象的属性是另一个对象,则工作方式相同。
    • 我试试看。我假设我只需要将 subjobject 声明为: property foo : TFoo read fFoo write fFoo;
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-07
    • 2015-07-09
    • 2023-03-10
    • 1970-01-01
    相关资源
    最近更新 更多