如何在 Delphi XE2 中解析嵌套的 JSON 对象?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10808912/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to parse nested JSON object in Delphi XE2?
提问by Bogdan Botezatu
I'm new to JSON and I have this project on my hands that require me to parse a JSON and display some of its contents in a ListView. The problem is that the documentation I've read by now dealt with JSON objects containing JSON arrays, while my case involves dealing with nested objects. To cut the story short, here's the summary: I'm using Delphi XE2 with DBXJSON. I post some values to a server and it replies with a JSON object that looks like that:
我是 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
}
What I wanted to achieve was to have each item (i.e. Purse) parsed and added as caption in a listview, along with one subitem (manufacturer). I created a procedure that takes the JSON string as argument, created the JSON object, but I don't know how to parse the nested objects any further.
我想要实现的是将每个项目(即钱包)解析并添加为列表视图中的标题,以及一个子项目(制造商)。我创建了一个将 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;
Any suggestions would be highly appreciated. Lost quite some time trying to get the ins and outs of JSON in Delphi with no avail.
任何建议将不胜感激。花了很多时间试图在 Delphi 中了解 JSON 的来龙去脉,但无济于事。
Thanks, sphynx
谢谢,斯芬克斯
回答by RRUZ
Try this sample
试试这个样本
{$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.
This will return
这将返回
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
回答by mgibsonbr
This sitedescribes the type TJSONValuein more detail. If your data is an object, it will have the type TJSONObject, so check its API to see how to proceed.
该站点TJSONValue更详细地描述了该类型。如果您的数据是一个对象,它将具有 type TJSONObject,因此请检查其 API 以了解如何继续。
I believe the first thing you need it to iterate over its pairs (use GetEnumeratorif you don't know the key names, otherwise just use the overloaded Get- passing a string instead of a number). For each pair, the key will be a simple string (type TJSONString) and the value may be any TJSONValue. Repeat until you reach the leaves.
我相信您首先需要它遍历其对(GetEnumerator如果您不知道键名,则使用它,否则只需使用重载Get- 传递一个字符串而不是数字)。对于每一对,键是一个简单的字符串(类型TJSONString),值可以是 any TJSONValue。重复直到你到达叶子。
Example:
例子:
products := jPair.Get('products');
purse := products.GetJsonValue().Get('Purse');
purseManuf := purse.GetJsonValue().Get('manufacturer');
...
Or if you don't know what the products are:
或者,如果您不知道产品是什么:
products := jPair.Get('products');
for prodPair in products.GetEnumerator() do
begin
prodName := prodPair.GetJsonString();
prodObj := prodPair.GetJsonValue();
...
回答by Please_Dont_Bully_Me_SO_Lords
This blog postshows a very modern and simple way to convert JSON:
这篇博文展示了一种非常现代且简单的 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;

