Delphi: 如何使用TJson.JsonToObject反序列化TList<T>?

3

考虑以下测试类:

TUser = class
  Name: string;
  constructor Create(AName: string);
end;

TTestClass = class
  Users:  TList<TUser>;
  constructor Create;
end;

将数据序列化为JSON格式没有问题,但是当我尝试反序列化时,列表没有被填充:

procedure TForm21.Button1Click(Sender: TObject);
var
  u: TUser;
begin
  TestClass := TTestClass.Create;
  TestClass.Users.Add( TUser.Create('Nick'));
  TestClass.Users.Add( TUser.Create('Mike'));

  Memo1.Text := TJson.ObjectToJsonString(TestClass);
  TestClass2 := TJson.JsonToObject<TTestClass>( Memo1.Text );

  for u in TestClass2.Users do
    Memo1.Lines.Add(Format('User %s ', [ u.Name ]));
end;

JSON输出如下:
{"users":{"listHelper":[2],"items":[["Nick"],["Mike"]]}}

我已经在Delphi 10.1 Berlin上确认了这个问题,并尝试使用TJSONMarshal和TJSONUnMarshal进行测试,但结果仍然是负面的。 - Marc Guillot
Delphi XE5用户也是空的。 - coding Bott
2个回答

2

字段名称通常以"f"为前缀。 当您将"users"重命名为"fUsers"时,您的代码将正常工作。

原因很简单,当您知道它时。 在json中,f看起来不好看。我猜这就是为什么当json生成时存在时,他们会将其删除,而在解析json时添加它的原因。

请参见单元REST.JsonReflect 方法: TJSONUnMarshal.ConvertFieldNameFromJson 和 TJSONConverter.ConvertFieldNameToJson


1

仅是扩展“@coding Bott”的答案。

如果你希望独立于“F”前缀,你可以使用单元REST.Json.Types中存在的 JSONNameAttribute ,以指定类中字段的名称。

您的示例可更改为:

TTestClass = class
  [JSONName('Users')]
  Users:  TList<TUser>;
  constructor Create;
end;

正如您在TJSONConverter.ConvertFieldNameToJson中所看到的,该方法首先检查是否应用了JsonNameAttribute,如果没有,则适用常规规则。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接