json - 将 JSON 反序列化为类型对象数组(Delphi 11)
问题描述
我正在尝试反序列化来自 Web 服务的 JSON 响应。响应采用类型良好的对象数组的形式。例如,我使用的是 songster.com。
在下面的(摘录)代码中,显然TSongsterResponse
是不正确的,因为我得到了一个集合。但两者都array of TSongsterResponse
不会TSongsterList
编译。
interface
type
TSongsterResponse = class
public
id: integer;
title: string;
end;
type TSongsterList = array of TSongsterResponse;
implementation
procedure Sample(AJson: string);
begin
// What goes here to get an array of TSongsterResponse?
FSomething := TJson.JsonToObject<?????>(RESTResponse1.Content);
end;
解决方案
TJson.JsonToObject()
,顾名思义,需要对象类型,而不是数组类型。它有一个 Generic 约束class, constructor
,这意味着它必须能够Create
反序列化成一个对象。它不能反序列化不在 JSON 对象内部的 JSON 数组。
您可以尝试使用 包装RESTResponse1.Content
,'{...}'
否则您可能只需要求助于使用并自己手动TJSONObject.ParseJSONValue()
构建(请参阅Delphi 解析 JSON 数组或数组)。TSongsterList
查看正在解析的实际 JSON 会有所帮助,但没有什么能阻止您定义自己的类类型以将 JSON 值复制到其中。例如:
interface
type
TSongsterResponse = class
public
id: integer;
title: string;
end;
TSongsterList = array of TSongsterResponse;
implementation
uses
System.JSON;
var
FSomething: TSongsterList;
procedure Sample(AJson: string);
var
Value: TJSONValue;
Arr: TJSONArray;
Obj: TJSONObject;
Song: TSongsterResponse;
I: Integer;
begin
Value := TJSONObject.ParseJSONValue(AJson);
if Value = nil then Exit;
try
Arr := Value as TJSONArray;
SetLength(FSomething, Arr.Count);
for I := 0 to Arr.Count-1 do
begin
Obj := Arr[I] as TJSONObject;
Song := TSongsterResponse.Create;
try
Song.id := (Obj.GetValue('id') as TJSONNumber).AsInt;
Song.title := Obj.GetValue('title').Value;
FSomething[I] := Song;
except
Song.Free;
raise;
end;
end;
finally
Value.Free;
end;
// use FSomething as needed...
end;
...
Sample(RESTResponse1.Content);
话虽如此,请注意它TRESTResponse
有一个JSONValue
属性可以为您解析接收到的 JSON 内容,例如:
interface
type
TSongsterResponse = class
public
id: integer;
title: string;
end;
TSongsterList = array of TSongsterResponse;
implementation
uses
System.JSON;
var
FSomething: TSongsterList;
procedure Sample(AJson: TJSONValue);
var
Arr: TJSONArray;
...
begin
Arr := AJson as TJSONArray;
// process Arr same as above...
// use FSomething as needed...
end;
...
Sample(RESTResponse1.JSONValue);
推荐阅读
- python - 如何清理嵌套字典的代码
- neo4j - neo4j-graphql-js:使用@cypher 满足类型而不返回具体节点
- azure - Azure 数据工厂:从 MI 存储 V1 获取 MI 令牌失败。错误代码 2403
- kotlin - 如何在 Kotlin Data 类中使用默认值以及 Micronaut 自省验证?
- r - 根据 R 中的规则从 data.frame 中删除行
- javascript - 在JS中按价格对项目数组进行排序忽略具有相同价格的元素
- stream - Rabbitmq:在 MQTT 中监听
- python - 在 Python 中填充数组 - 来自 C 等效项
- email - AppleScript:在邮件应用程序中从列表中创建 SmartInbox
- discord-jda - Discord JDA:GuildSetupController -> Bot 无法再准备就绪