Forum > General
Complex objects and JsonObjects
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.
Flea:
Hi, has this change been implemented/checked yet? Or is it due to be ?
Many Thanks
Navigation
[0] Message Index
[*] Previous page