#1 2017-03-26 19:47:00

mohsenti
Member
Registered: 2015-04-11
Posts: 72

Choose JSON Serialization classes

Hi,

I have JSON like this:

{
	"ID": 1,
	"Childs": [{
			"ID": 2,
			"Typ": "C1",
			"Name1":"X"
		}, {
			"ID": 3,
			"Typ": "C2",
			"Name2":"Y"
		}
	]
}

Childs can have different classes with different types but I have an array with base Child class, so I made something like this:

type
  TParentItem = class;
  TParentItems = array of TParentItem;

  { TItem }

  TItem = class(TSynAutoCreateFields)
  private
    FID: integer;
  published
    property ID: integer read FID write FID;
  end;

  { TParentItem }

  TParentItem = class(TItem)
  private
    FChilds: TParentItems;
    FTestItem: TItem;
  published
    property TestItem: TItem read FTestItem;
    property Childs: TParentItems read FChilds write FChilds;
  end;

  { TParentItem1 }

  TParentItem1 = class(TParentItem)
  private
    FName1: string;
  published
    property Name1: string read FName1 write FName1;
  end;

  { TParentItem2 }

  TParentItem2 = class(TParentItem)
  private
    FName2: string;
  published
    property Name2: string read FName2 write FName2;
  end;              

How can I choose what class should be made for array item? I have "Typ" value to choose that but making a CustomSerializer wont help becuase it pass a const object and I can change the value of it.
Is there a way to pass a custom create function so in there I can check the "Typ" value and choose that?

Offline

#2 2017-03-26 20:35:43

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,655
Website

Re: Choose JSON Serialization classes

You have an option to specify the classname during serialization.

Offline

#3 2017-03-26 21:58:40

mohsenti
Member
Registered: 2015-04-11
Posts: 72

Re: Choose JSON Serialization classes

Thanks, but where is it?
If you mean this https://synopse.info/files/html/Synopse … ml#TITL_71 I cant understand how it can help because it need "ClassName" value but I get this JSON from another sever and the value is "Type" for example.

I'm still looking for a solution in documentation and the code and the best I found is something like this and it seems it works.

  procedure TestIt;
  var
    it: TParentItem;
    s: RawUTF8;
  begin
    TJSONSerializer.RegisterObjArrayForJSON([TypeInfo(TParentItems), TParentItem]);
    TTextWriter.RegisterCustomJSONSerializer(TypeInfo(TParentItems), TSReaderWriter.ParentItemsReader, nil);
    s := StringFromFile('test.json');
    it := TParentItem.Create;
    ObjectLoadJSON(it, s, nil, [j2oIgnoreUnknownProperty]);
    ObjectToJSONFile(it, 'output.json');
    it.Free;
  end;

  { TSReaderWriter }

  class function TSReaderWriter.ParentItemsReader(P: PUTF8Char; var aValue; out aValid: boolean): PUTF8Char;
   var
    V: TObject absolute aValue;
    typ: string;
    op:RawUTF8;
  begin
    aValid := False;
    Result := nil;
    if (p = nil) then
      exit;
    if (V = nil) then
    begin
      op:=UTF8ToString(P);
      if typ = 'C1' then
        V := TParentItem1.Create
      else if typ = 'C2' then
        V := TParentItem2.Create
      else
        V := TParentItem.Create;
    end;
    result := JSONToObject(aValue, P, aValid, nil, JSONTOOBJECT_TOLERANTOPTIONS);    
  end;                    

Last edited by mohsenti (2017-03-26 22:39:02)

Offline

#4 2017-03-29 15:33:19

mohsenti
Member
Registered: 2015-04-11
Posts: 72

Re: Choose JSON Serialization classes

Is this way right from your view?

Offline

Board footer

Powered by FluxBB