将JSON反序列化为类型化对象数组( Delphi 11)

wwwo4jvm  于 2022-12-12  发布在  其他
关注(0)|答案(1)|浏览(328)

我尝试反序列化来自Web服务的JSON响应。响应的形式是类型良好的对象数组。作为一个例子,我使用songster.com。
在下面的代码中,TSongsterResponse显然是不正确的,因为我得到的是一个集合,但是array of TSongsterResponseTSongsterList都不会编译。

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;
j91ykkif

j91ykkif1#

TJson.JsonToObject(),顾名思义,需要一个对象类型,而不是数组类型。它有一个泛型约束class, constructor,这意味着它必须能够将对象Create反序列化到其中。它不能反序列化不在JSON对象内部的JSON数组。
您可以尝试用'{...}' Package RESTResponse1.Content,否则您可能不得不转而使用TJSONObject.ParseJSONValue()并自己手动构建TSongsterList(请参见Delphi parse JSON array or array)。
查看正在解析的实际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);

相关问题