Recent

Author Topic: ezjson - JSON serialize / deserialize with attributes  (Read 378 times)

mr-highball

  • Full Member
  • ***
  • Posts: 111
ezjson - JSON serialize / deserialize with attributes
« on: January 03, 2020, 12:49:26 am »
Hey everyone, hope everyone had a good start to the new year  :D
The past few days I've been working on JSON serialization / deserialization using custom attributes. These work by attaching two types of decorators to either your classes / interfaces or to properties of classes / interfaces.
Each decorator simply takes a name to be used when when serializing

JsonObject('objectName')
JsonProperty('propertyName')

Once you have your decorated objects, you can then call one of two generic methods,
EZSerialize<T>(...) (outputs json)
EZDeSerialize<T>(...) (input json)

An example is worth a 1000 words, so here you go,

Code: Pascal  [Select]
  1.   { TTestDecorated }
  2.   (*
  3.     a simple object decorated with a custom name to be used when serializing and
  4.     deserializing, as well as some simple typed properties to include in
  5.     serialization
  6.   *)
  7.   [JsonObject('myTestObject')]
  8.   TTestDecorated = class(TObject)
  9.   private
  10.     FTest : String;
  11.     FTestInt : Integer;
  12.   published
  13.     [JsonProperty('test')]
  14.     property Test : String read FTest write FTest;
  15.  
  16.     [JsonProperty('testInteger')]
  17.     property TestInt : Integer read FTestInt write FTestInt;
  18.   end;
  19.  
  20.   ...
  21.  
  22. procedure TestSimple;  
  23. var
  24.   LTest : TTestDecorated;
  25.   LJSON,
  26.   LError : String;
  27. begin
  28.   //setting a value on our test
  29.   LTest := TTestDecorated.Create;
  30.   LTest.Test := 'a test';
  31.  
  32.   //calling serialize
  33.   if not (EZSerialize<TTestDecorated>(LTest, LJSON, LError)) then
  34.     raise Exception.Create(LError) //failed to serialize
  35.   else
  36.     WriteLn(LJSON); //success
  37. end;
  38.  

the output from above is below,
{ "myTestObject" : { "test" : "a value", "testInteger" : 0 } }

Nested object or interface properties can also be used in conjunction with standard types, here's another example (minus the calling code for brevity)

Code: Pascal  [Select]
  1. TTestComplex = class(TObject)
  2.   private
  3.     FDecorated: TTestDecorated;
  4.     FNonDecorated: TTestNonDecorated;
  5.   public
  6.     constructor Create;
  7.     destructor Destroy; override;
  8.   published
  9.     [JsonProperty('decorated')]
  10.     property Decorated : TTestDecorated read FDecorated;
  11.  
  12.     [JsonProperty('nonDecorated')]
  13.     property NonDecorated : TTestNonDecorated read FNonDecorated;
  14.   end;
  15.  

and here's the output when serialized,

{ "TestComplex" : { "decorated" : { "test" : "a value", "testInteger" : 0 }, "nonDecorated" : { "test" : "" } } }

I'm actively working on this, and right now only serialization has been implemented (still working on deserialize  :-[ ) but I thought someone might find some use or could provide a second set of eyes.

here's the repo, https://github.com/mr-highball/ezjson

Cheers 🍻
« Last Edit: January 03, 2020, 01:06:00 am by mr-highball »
-Highball

mr-highball

  • Full Member
  • ***
  • Posts: 111
Re: ezjson - JSON serialize / deserialize with attributes
« Reply #1 on: February 11, 2020, 04:32:01 pm »
running into some rtti issues, that are stalling finishing this library up reported here -> https://bugs.freepascal.org/view.php?id=36651

serialize "should" be ok, and deserialize is in a rough draft state but isn't properly working (either misunderstanding on my part or bug)

the bug report has my test cases and descriptions of each,
if anyone can help out and look over that would be nice :)
-Highball