Forum > General

Complex objects and JsonObjects

<< < (2/2)

LeoBruno:
This is amazing!

Thank you very much!

When I asked about the completion of the extended RTTI, I was not thinking about this issue specifically.

Regards....


--- Quote from: PascalDragon on July 31, 2022, 02:13:16 pm ---
--- Quote from: LeoBruno on July 30, 2022, 06:25:21 pm ---I also need to load the object from Json string.

Can you help me?
--- End quote ---

For this you need to use TJSONDeStreamer correctly (see extended example below).


--- Quote from: LeoBruno on July 30, 2022, 06:25:21 pm ---Is the extended rtti far from completion?
--- End quote ---

The Extended RTTI wouldn't help here, also it's not even needed here, because everything you can stream with the normal RTTI you can destream with it as well (you just need to know how).


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---program tgenrtti; {$mode objfpc}{$H+} uses  SysUtils, Generics.Collections, fpjsonrtti, typinfo, fpjson; type  {$push}  {$M+}  TTestObject = class  private    fField1: LongInt;    fField2: String;  published    property Field1: LongInt read fField1 write fField1;    property Field2: String read fField2 write fField2;  end;   TObjectListTestObject = specialize TObjectList<TTestObject>;   TTestContainer = class  private    fContainer: TObjectListTestObject;    fField1: String;  public    constructor Create;    destructor Destroy; override;  published    property Field1: String read fField1 write fField1;    property Container: TObjectListTestObject read fContainer;  end;  {$pop}   TMyStreamer = class(TJSONStreamer)  protected    function StreamClassProperty(const aObject: TObject): TJSONData; override;  end;   { THandler }   THandler = class    procedure HandleRestoreProperty(aSender: TObject; aObject: TObject; aInfo: PPropInfo; aValue: TJSONData; var aHandled: Boolean);    procedure HandleGetObject(aSender: TObject; aObject: TObject; aInfo: PPropInfo; aData: TJSONObject; aDataName: TJSONStringType; var aValue: TObject);  end; { THandler } procedure THandler.HandleRestoreProperty(aSender: TObject; aObject: TObject;  aInfo: PPropInfo; aValue: TJSONData; var aHandled: Boolean);var  destrm: TJSONDeStreamer absolute aSender;  arr: TJSONArray absolute aValue;  list: TObjectListTestObject;  o: TTestObject;  i: SizeInt;begin  if not (aSender is TJSONDeStreamer) then    raise EJSONRTTI.Create('Sender has invalid type');   if aInfo^.PropType = TObjectListTestObject.ClassInfo then begin    if aValue is TJSONArray then begin      list := TObjectListTestObject(GetObjectProp(aObject, aInfo));      for i := 0 to arr.Count - 1 do begin        o := TTestObject.Create;        if not (arr[i] is TJSONObject) then          raise EJSONRTTI.CreateFmt('Element %d is not an object', [i]);        destrm.JSONToObject(TJSONObject(arr[i]), o);        list.Add(o);      end;      aHandled := True;    end;  end;end; procedure THandler.HandleGetObject(aSender: TObject; aObject: TObject;  aInfo: PPropInfo; aData: TJSONObject; aDataName: TJSONStringType;  var aValue: TObject);var  destrm: TJSONDeStreamer absolute aSender;begin  if not (aSender is TJSONDeStreamer) then    raise EJSONRTTI.Create('Sender has invalid type');   if aInfo^.PropType = TTestObject.ClassInfo then    aValue := TTestObject.Create;   if Assigned(aValue) then    destrm.JSONToObject(aData, aValue);end; { TMyStreamer } function TMyStreamer.StreamClassProperty(const aObject: TObject): TJSONData;var  arr: TJSONArray absolute Result;  olTestObject: TObjectListTestObject absolute aObject;  i: SizeInt;begin  if aObject is TObjectListTestObject then begin    Result := TJSONArray.Create;    for i := 0 to olTestObject.Count - 1 do begin      arr.Add(ObjectToJSON(olTestObject[i]));    end;  end else    Result := inherited StreamClassProperty(AObject);end; { TTestContainer } constructor TTestContainer.Create;begin  fContainer := TObjectListTestObject.Create;end; destructor TTestContainer.Destroy;begin  fContainer.Free;  inherited Destroy;end; var  c: TTestContainer;  o: TTestObject;  s: TJSONStreamer;  d: TJSONDeStreamer;  j: TJSONStringType;  i: SizeInt;  handler: THandler;begin  c := TTestContainer.Create;  try    c.Field1 := 'My Container';     o := TTestObject.Create;    o.Field1 := 42;    o.Field2 := 'Hello World';    c.Container.Add(o);     o := TTestObject.Create;    o.Field1 := 21;    o.Field2 := 'Foobar';    c.Container.Add(o);     s := TMyStreamer.Create(Nil);    try      j := s.ObjectToJSONString(c);      Writeln(j);    finally      s.Free;    end;     c.Free;    c := TTestContainer.Create;     handler := Nil;    d := TJSONDeStreamer.Create(Nil);    try      handler := THandler.Create;       { this is only needed if you have class type properties instead of only        primitive types as well }      //d.OnGetObject := @handler.HandleGetObject;      d.OnRestoreProperty := @handler.HandleRestoreProperty;       d.JSONToObject(j, c);    finally      handler.Free;      d.Free;    end;     Writeln('Field1: ', c.Field1);    Writeln('Count: ', c.Container.Count);    for i := 0 to c.Container.Count - 1 do begin      o := c.Container[i];      Writeln('   Element ', i, ':');      Writeln('      Field1: ', o.Field1);      Writeln('      Field2: ', o.Field2);    end;  finally    c.Free;  end;end.
--- End quote ---

PascalDragon:

--- Quote from: LeoBruno on July 31, 2022, 07:44:39 pm ---When I asked about the completion of the extended RTTI, I was not thinking about this issue specifically.
--- End quote ---

There already exists a finished merge request for it, but I need to find the time to review it.

Navigation

[0] Message Index

[*] Previous page

Go to full version