当我使用 TJson.ObjectToJsonString 将对象序列化为 json 时,如何动态忽略属性

发布于 2025-01-18 17:39:58 字数 1336 浏览 0 评论 0原文

我有这个类:

unit untPerson;
interface
type TPerson = class
  private
    fName  : string;
    fEmail : string;
    fAge   : integer;
  published 
    property Name  : string  read fName  write fName;
    property Email : string  read fEmail write fEmail;
    property Age   : integer read fAge   write fAge;
end;
implementation
end.

我需要使用此代码序列化为 Json

TJson.ObjectToJsonString(objPerson, []);

但如果等于 0,我需要跳过 Age。

if objPerson.Age = 0 then
  result := '{"name":"Lucas", "email":"[email protected]"}'
else
  result := '{"name":"Lucas", "email":"[email protected]", "age":30}';

我该怎么办?

if objPerson.Age = 0 then
  result := '{"name":"Lucas", "email":"[email protected]"}'
else
  result := '{"name":"Lucas", "email":"[email protected]", "age":30}';

I have this class:

unit untPerson;
interface
type TPerson = class
  private
    fName  : string;
    fEmail : string;
    fAge   : integer;
  published 
    property Name  : string  read fName  write fName;
    property Email : string  read fEmail write fEmail;
    property Age   : integer read fAge   write fAge;
end;
implementation
end.

And i need to serialize to Json using this code

TJson.ObjectToJsonString(objPerson, []);

But i need to skip Age if equal 0.

if objPerson.Age = 0 then
  result := '{"name":"Lucas", "email":"[email protected]"}'
else
  result := '{"name":"Lucas", "email":"[email protected]", "age":30}';

How Can I Do?

if objPerson.Age = 0 then
  result := '{"name":"Lucas", "email":"[email protected]"}'
else
  result := '{"name":"Lucas", "email":"[email protected]", "age":30}';

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

萧瑟寒风 2025-01-25 17:39:58

您无法使用以下代码动态忽略属性:TJson.ObjectToJsonString(objPerson, []);
您可以通过自定义 TJSONInterceptor 放置空字符串,就像 Remy Lebeau 在评论中所说的那样(https://en.delphipraxis.net/topic/6155-tjson-suppressemptyvalues-for-empty-integer-double-and-class-fields/),但要将其从 json 中排除,您需要输入选项 joIgnoreEmptyStrings :TJson.ObjectToJsonString(objPerson, [joIgnoreEmptyStrings]);。

另一种方法是:使用自定义转换器(TJsonConverter 的后代),但问题是在这种情况下您不能使用 TJson.ObjectToJsonString,因为它已预编译专门使用 TJSONConverter 类创建 JSONMarshal 的代码,无法覆盖:TJSONMarshal.Create(TJSONConverter.Create,真,CFRegConverters);。因此,您需要重新实现所有调用链 TJSON.ObjectToJsonString -> ObjectToJsonValue -> TJSONConverters.GetJSONMarshaler -> TJSONMarshal.Create(TJSONConverter.Create, true, CFRegConverters);。之后您必须使用这个自定义实现。

最简单的方法 - 将自定义方法直接添加到类中:

  TPerson = class
  private
    fName  : string;
    fEmail : string;
    fAge   : integer;
  published
    function ToJsonString : string; virtual;
    class function FromJsonString(const AJsonStr : string) : TPerson;
    property Name  : string  read fName  write fName;
    property Email : string  read fEmail write fEmail;
    property Age   : integer read fAge   write fAge;
    end;

在这种情况下 - 您可以使用任何自定义逻辑,但相同的代码:TJson.ObjectToJsonString(objPerson, []);.will 无法正常工作。您必须使用这些新方法。

最后 – 您可以尝试找到一些其他 3rd 方 JSON 序列化器。

You can't dynamically ignore properties by using code: TJson.ObjectToJsonString(objPerson, []);.
You can put empty string by custom TJSONInterceptor, like Remy Lebeau says in comments(https://en.delphipraxis.net/topic/6155-tjson-suppressemptyvalues-for-empty-integer-double-and-class-fields/), but to exclude it from json you need to put option joIgnoreEmptyStrings: TJson.ObjectToJsonString(objPerson, [joIgnoreEmptyStrings]);.

One more way to do it: use custom converter (descendant of TJsonConverter), but problem is that you can’t use TJson.ObjectToJsonString in this case, because it have precompiled code with creating JSONMarshal using specifically TJSONConverter class without possibility of overriding: TJSONMarshal.Create(TJSONConverter.Create, true, CFRegConverters);. So you need to reimplement all chain of call TJSON.ObjectToJsonString -> ObjectToJsonValue -> TJSONConverters.GetJSONMarshaler -> TJSONMarshal.Create(TJSONConverter.Create, true, CFRegConverters);. And after that you must use this custom implementation.

Easiest way – to add custom method directly to class:

  TPerson = class
  private
    fName  : string;
    fEmail : string;
    fAge   : integer;
  published
    function ToJsonString : string; virtual;
    class function FromJsonString(const AJsonStr : string) : TPerson;
    property Name  : string  read fName  write fName;
    property Email : string  read fEmail write fEmail;
    property Age   : integer read fAge   write fAge;
    end;

In this case – you can use any custom logic, but the same code: TJson.ObjectToJsonString(objPerson, []);.will does not work correctly. You must use these new methods.

And last – you can try to find some other 3rd party JSON serializers.

木格 2025-01-25 17:39:58

作为替代解决方案, mORMot 有这个菱形,并且您始终可以使用 ObjectToJson 以集中方式非常快速地序列化任何 TObject:

program TestJson;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  Syncommons, mORMot;

type TPerson = class
  private
    fName  : string;
    fEmail : string;
    fAge   : integer;
  public
    class procedure ClassWriter(const aSerializer: TJSONSerializer;
                                aValue: TObject; aOptions: TTextWriterWriteObjectOptions);
  published
    property Name  : string  read fName  write fName;
    property Email : string  read fEmail write fEmail;
    property Age   : integer read fAge   write fAge;
end;

{ TPerson }

class procedure TPerson.ClassWriter(const aSerializer: TJSONSerializer;
                                    aValue: TObject; aOptions: TTextWriterWriteObjectOptions);
var Person: TPerson absolute aValue;
begin
  if Person.Age=0 then
    aSerializer.AddJSONEscape(['Name',Person.Name,
                               'Email',Person.Email
                              ])
  else
    aSerializer.AddJSONEscape(['Name',Person.Name,
                               'Email',Person.Email,
                               'Age',Person.Age
                              ]);
end;

var Person : TPerson;
begin
  TJSONSerializer.RegisterCustomSerializer(TPerson,nil,TPerson.ClassWriter);
  Person := TPerson.Create;
  try
    Person.Name := 'Jon';
    Person.Email := '[email protected]';
    Person.Age := 10;
    writeln(ObjectToJson(Person)); // Result {"Name":"Jon","Email":"[email protected]","Age":10}

    Person.Age := 0;
    writeln(ObjectToJson(Person)); // Result {"Name":"Jon","Email":"[email protected]"}
  finally
    Person.Free;
  end;
  readln;
end.

请在 令人惊叹的文档

As an alternative solution, mORMot have this diamond, and you can always use ObjectToJson to serialize very fast any TObject in a centralized way:

program TestJson;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  Syncommons, mORMot;

type TPerson = class
  private
    fName  : string;
    fEmail : string;
    fAge   : integer;
  public
    class procedure ClassWriter(const aSerializer: TJSONSerializer;
                                aValue: TObject; aOptions: TTextWriterWriteObjectOptions);
  published
    property Name  : string  read fName  write fName;
    property Email : string  read fEmail write fEmail;
    property Age   : integer read fAge   write fAge;
end;

{ TPerson }

class procedure TPerson.ClassWriter(const aSerializer: TJSONSerializer;
                                    aValue: TObject; aOptions: TTextWriterWriteObjectOptions);
var Person: TPerson absolute aValue;
begin
  if Person.Age=0 then
    aSerializer.AddJSONEscape(['Name',Person.Name,
                               'Email',Person.Email
                              ])
  else
    aSerializer.AddJSONEscape(['Name',Person.Name,
                               'Email',Person.Email,
                               'Age',Person.Age
                              ]);
end;

var Person : TPerson;
begin
  TJSONSerializer.RegisterCustomSerializer(TPerson,nil,TPerson.ClassWriter);
  Person := TPerson.Create;
  try
    Person.Name := 'Jon';
    Person.Email := '[email protected]';
    Person.Age := 10;
    writeln(ObjectToJson(Person)); // Result {"Name":"Jon","Email":"[email protected]","Age":10}

    Person.Age := 0;
    writeln(ObjectToJson(Person)); // Result {"Name":"Jon","Email":"[email protected]"}
  finally
    Person.Free;
  end;
  readln;
end.

Please, find further details in the amazing documentation

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文