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}';
CodePudding user response:
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.
CodePudding user response:
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;
JsonPerson : string;
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