Json 数组到 ListBox/Memo in Delphi xe7
Json Array into ListBox/Memo in Delphi xe7
我正在尝试捕获以下 JSON 数组:
[{"name":"Bryan","email":"Bryan@hotmail.com"},
{"name":"Louis","email":"Louis@hotmail.com"},
{"name":"Maria","email":"Maria@hotmail.com"},
{"name":"Test","email":"test@hotmail.com"},
{"name":"Anthony","email":"anthony@hotmail.com"}]
并将其放入 Delphi 中的 Memo
或 ListBox
中:
代码如下:
procedure TForm1.Button1Click(Sender: TObject);
var jv: TJSONValue;
jo: TJSONObject;
jp: TJSONPair;
ja: TJSONArray;
i: integer;
j: integer;
begin
RESTRequest1.Execute;
jv:=RESTResponse1.JSONValue;
jo:= TJSONObject.ParseJSONValue(jv.ToString) as TJSONObject;
try
for i := 0 to jo.Size - 1 do
begin
jp := jo.Get(i);
if jp.JsonValue is TJSONArray then
begin
ja := jp.JsonValue as TJSONArray;
for j := 0 to ja.Size -1 do
Memo1.Lines.Add(ja.Get(i).ClassName + ': ' + ja.Get(j).ToString);
end
else
Memo1.Lines.Add(jp.ClassName + ': '+ jp.ToString);
end;
finally
jo.Free;
end;
end;
当我点击按钮时,我收到以下错误消息:
Invalid class typecast
在调试过程中,以下行有问题:
jo:= TJSONObject.ParseJSONValue(jv.ToString) as TJSONObject;
我不知道如何解决这个问题或这个错误,
你能帮帮我吗?
谢谢。
这完全可以通过阅读代码和查看 JSON 来解决。但是,我想向您展示如何调试此类问题,以防您无法通过静态分析解决该问题。当 as
转换失败时,总是因为 as
左侧的对象不是从右侧的类型派生的。下一步总是询问左侧对象的类型是什么。我在上面包含了一个简短的 MCVE 作为演示的方式。
这个程序的输出:
{$APPTYPE CONSOLE}
uses
System.JSON;
const
JSON = '[{"name":"Bryan","email":"Bryan@hotmail.com"},' +
' {"name":"Louis","email":"Louis@hotmail.com"},' +
' {"name":"Maria","email":"Maria@hotmail.com"},' +
' {"name":"Test","email":"test@hotmail.com"},' +
' {"name":"Anthony","email":"anthony@hotmail.com"}]';
begin
Writeln(TJSONObject.ParseJSONValue(JSON).ClassName);
end.
是
TJSONArray
现在,TJSONArray
不派生自 TJSONObject
。因此,您的 as
转换会引发运行时错误。如果将 ParseJSONValue
返回的值转换为 TJSONArray
,那将会成功。
这是意料之中的,因为您的 JSON 的根是一个数组而不是对象。
您需要修改您的代码,使其不假定根级别始终是一个对象。数组和对象需要不同的行为。
我不确定 TJSONObject
的问题与您发布的字符串有关。
出于某种原因,如果您更改它,它会解析它。
{"Persons":[{"name":"Bryan","email":"Bryan@hotmail.com"},{"name":"Louis","email":"Louis@hotmail.com"},{"name":"Maria","email":"Maria@hotmail.com"},{"name":"Test","email":"test@hotmail.com"},{"name":"Anthony","email":"anthony@hotmail.com"}]}
如果我运行原样的代码,我会得到以下结果
如果您不介意使用与默认 Delphi 单位不同的东西,我建议您使用 superobject (Link here)
superobject 将解析您的 JSON 编辑和发布。
您的代码如下所示:
Const
MyJSON = '[{"name":"Bryan","email":"Bryan@hotmail.com"},{"name":"Louis","email":"Louis@hotmail.com"},{"name":"Maria","email":"Maria@hotmail.com"},{"name":"Test","email":"test@hotmail.com"},{"name":"Anthony","email":"anthony@hotmail.com"}]';
procedure ParseJSON;
var
obj: ISuperObject;
Ar: TSuperArray;
I: integer;
begin
obj := SO(MyJSON);
if obj.IsType(stArray) then
begin
Ar := obj.AsArray;
try
for I := 0 to Ar.Length-1 do
L.Add(Ar.O[I].AsString);
finally
Ar.Free;
end;
end
else
L.Add(Obj.AsString);
end;
结果:
对于 Koul,获取元素名称和值。
就像我说的不是很漂亮的代码但是还可以。
Ar.O[0].AsObject.GetNames.AsArray.S[0]
把它切碎一点。
Ar.O[0] //Get the first element in the array as ISuperObject
.AsObject //Get it as TSuperTableString
.GetNames //Gets all names in the array, in this case "name" and "email"
.AsArray[0]//Get the first name in the names array.
它将导致 email
(名称按 A-Z 排序)
您可以通过调用 GetValues
而不是 GetNames
来对值执行相同的操作。
我认为获得它的最漂亮的方法是多定义 2 倍 TSuperArray
procedure PrintNamesAndValues;
Var
Ar, ArNames, ArValues:TSuperArray;
I: Integer;
begin
Ar := SO(<JSON string>).asArray;
ArNames := Ar.O[0].AsObject.GetNames.AsArray;
ArValues := Ar.O[0].AsObject.GetValues.AsArray;
For I := 0 to ArNames.Length-1 do
WriteLn(Format('%s: %s',[ArNames.S[I], ArValues.S[I]]));
end;
希望一切都足够清楚:)
我正在尝试捕获以下 JSON 数组:
[{"name":"Bryan","email":"Bryan@hotmail.com"}, {"name":"Louis","email":"Louis@hotmail.com"}, {"name":"Maria","email":"Maria@hotmail.com"}, {"name":"Test","email":"test@hotmail.com"}, {"name":"Anthony","email":"anthony@hotmail.com"}]
并将其放入 Delphi 中的 Memo
或 ListBox
中:
代码如下:
procedure TForm1.Button1Click(Sender: TObject);
var jv: TJSONValue;
jo: TJSONObject;
jp: TJSONPair;
ja: TJSONArray;
i: integer;
j: integer;
begin
RESTRequest1.Execute;
jv:=RESTResponse1.JSONValue;
jo:= TJSONObject.ParseJSONValue(jv.ToString) as TJSONObject;
try
for i := 0 to jo.Size - 1 do
begin
jp := jo.Get(i);
if jp.JsonValue is TJSONArray then
begin
ja := jp.JsonValue as TJSONArray;
for j := 0 to ja.Size -1 do
Memo1.Lines.Add(ja.Get(i).ClassName + ': ' + ja.Get(j).ToString);
end
else
Memo1.Lines.Add(jp.ClassName + ': '+ jp.ToString);
end;
finally
jo.Free;
end;
end;
当我点击按钮时,我收到以下错误消息:
Invalid class typecast
在调试过程中,以下行有问题:
jo:= TJSONObject.ParseJSONValue(jv.ToString) as TJSONObject;
我不知道如何解决这个问题或这个错误, 你能帮帮我吗?
谢谢。
这完全可以通过阅读代码和查看 JSON 来解决。但是,我想向您展示如何调试此类问题,以防您无法通过静态分析解决该问题。当 as
转换失败时,总是因为 as
左侧的对象不是从右侧的类型派生的。下一步总是询问左侧对象的类型是什么。我在上面包含了一个简短的 MCVE 作为演示的方式。
这个程序的输出:
{$APPTYPE CONSOLE}
uses
System.JSON;
const
JSON = '[{"name":"Bryan","email":"Bryan@hotmail.com"},' +
' {"name":"Louis","email":"Louis@hotmail.com"},' +
' {"name":"Maria","email":"Maria@hotmail.com"},' +
' {"name":"Test","email":"test@hotmail.com"},' +
' {"name":"Anthony","email":"anthony@hotmail.com"}]';
begin
Writeln(TJSONObject.ParseJSONValue(JSON).ClassName);
end.
是
TJSONArray
现在,TJSONArray
不派生自 TJSONObject
。因此,您的 as
转换会引发运行时错误。如果将 ParseJSONValue
返回的值转换为 TJSONArray
,那将会成功。
这是意料之中的,因为您的 JSON 的根是一个数组而不是对象。
您需要修改您的代码,使其不假定根级别始终是一个对象。数组和对象需要不同的行为。
我不确定 TJSONObject
的问题与您发布的字符串有关。
出于某种原因,如果您更改它,它会解析它。
{"Persons":[{"name":"Bryan","email":"Bryan@hotmail.com"},{"name":"Louis","email":"Louis@hotmail.com"},{"name":"Maria","email":"Maria@hotmail.com"},{"name":"Test","email":"test@hotmail.com"},{"name":"Anthony","email":"anthony@hotmail.com"}]}
如果我运行原样的代码,我会得到以下结果
如果您不介意使用与默认 Delphi 单位不同的东西,我建议您使用 superobject (Link here)
superobject 将解析您的 JSON 编辑和发布。
您的代码如下所示:
Const
MyJSON = '[{"name":"Bryan","email":"Bryan@hotmail.com"},{"name":"Louis","email":"Louis@hotmail.com"},{"name":"Maria","email":"Maria@hotmail.com"},{"name":"Test","email":"test@hotmail.com"},{"name":"Anthony","email":"anthony@hotmail.com"}]';
procedure ParseJSON;
var
obj: ISuperObject;
Ar: TSuperArray;
I: integer;
begin
obj := SO(MyJSON);
if obj.IsType(stArray) then
begin
Ar := obj.AsArray;
try
for I := 0 to Ar.Length-1 do
L.Add(Ar.O[I].AsString);
finally
Ar.Free;
end;
end
else
L.Add(Obj.AsString);
end;
结果:
对于 Koul,获取元素名称和值。
就像我说的不是很漂亮的代码但是还可以。
Ar.O[0].AsObject.GetNames.AsArray.S[0]
把它切碎一点。
Ar.O[0] //Get the first element in the array as ISuperObject
.AsObject //Get it as TSuperTableString
.GetNames //Gets all names in the array, in this case "name" and "email"
.AsArray[0]//Get the first name in the names array.
它将导致 email
(名称按 A-Z 排序)
您可以通过调用 GetValues
而不是 GetNames
来对值执行相同的操作。
我认为获得它的最漂亮的方法是多定义 2 倍 TSuperArray
procedure PrintNamesAndValues;
Var
Ar, ArNames, ArValues:TSuperArray;
I: Integer;
begin
Ar := SO(<JSON string>).asArray;
ArNames := Ar.O[0].AsObject.GetNames.AsArray;
ArValues := Ar.O[0].AsObject.GetValues.AsArray;
For I := 0 to ArNames.Length-1 do
WriteLn(Format('%s: %s',[ArNames.S[I], ArValues.S[I]]));
end;
希望一切都足够清楚:)