Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Interface mit TJsonSerializer (https://www.delphipraxis.net/193595-interface-mit-tjsonserializer.html)

Nathan 18. Aug 2017 10:55

Interface mit TJsonSerializer
 
Hallo

Experimentiere gerade mit der Klasse TJsonSerializer aus System.JSON.Serializers von Tokyo. Scheint ziemlich gut und einfach zu bedienen zu sein.
Da bei mir jede Klasse von einem Interface kommt, sind Properties immer an ein Interface gebunden. Der Serializer serialisiert aber nur Klassen, keine Interface.
Delphi-Quellcode:
program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.JSON.Serializers,
  System.JSON.Types,
  System.SysUtils;

{$M+}

type
  IFooOne = interface
    ['{1DA05420-61BD-404F-BD6F-15D638FE0CB5}']
    function GetOneProp(): Integer;
    procedure SetOneProp(Value: Integer);

    property OneProp: Integer read GetOneProp write SetOneProp;
  end;

  IFooSecond = interface
    ['{0D31D4A7-F31A-4B1A-8767-0DBD08BD97EA}']
    function GetSecondProp(): string;
    procedure SetSecondProp(const Value: string);

    function GetSecondObj(): IFooOne;
    procedure SetSecondObj(const Value: IFooOne);

    function ToJson(): string;

    property SecondProp: string read GetSecondProp write SetSecondProp;
    property SecondObj: IFooOne read GetSecondObj write SetSecondObj;
  end;


  TFooOne = class(TInterfacedObject, IFooOne)
  strict private
    FOneProp: Integer;
  private
    function GetOneProp(): Integer;
    procedure SetOneProp(Value: Integer);
  end;

  [JsonSerialize(TJsonMemberSerialization.&In)]
  TFooSecond = class(TInterfacedObject, IFooSecond)
  strict private
    [JsonName('SecondProp')] [JsonIn] FSecondProp: string;
    [JsonName('SecondObj')] [JsonIn] FSecondObj: IFooOne;
  private
    function GetSecondProp(): string;
    procedure SetSecondProp(const Value: string);

    function GetSecondObj(): IFooOne;
    procedure SetSecondObj(const Value: IFooOne);
  public
    function ToJson(): string;
  end;

{$M-}

{ TFooOne }

function TFooOne.GetOneProp: Integer;
begin
  Result := FOneProp;
end;

procedure TFooOne.SetOneProp(Value: Integer);
begin
  FOneProp := Value;
end;

{ TFooSecond }

function TFooSecond.GetSecondProp(): string;
begin
  Result := FSecondProp;
end;

function TFooSecond.GetSecondObj(): IFooOne;
begin
  Result := FSecondObj;
end;

procedure TFooSecond.SetSecondProp(const Value: string);
begin
  FSecondProp := Value;
end;

procedure TFooSecond.SetSecondObj(const Value: IFooOne);
begin
  FSecondObj := Value;
end;

function TFooSecond.ToJson: string;
var
  Serializer: TJsonSerializer;
begin
  Serializer := TJsonSerializer.Create;
  try
    Serializer.Formatting := TJsonFormatting.Indented;
    Result := Serializer.Serialize(Self);
  finally
    Serializer.Free;
  end;
end;


var
  Return: string;
  FooImpl1: IFooOne;
  FooImpl2: IFooSecond;

begin
  ReportMemoryLeaksOnShutdown := True;

  FooImpl1 := TFooOne.Create;
  FooImpl1.OneProp := 4711;

  FooImpl2 := TFooSecond.Create;
  FooImpl2.SecondProp := 'My second property.';
  FooImpl2.SecondObj := FooImpl1;
  Return := FooImpl2.ToJson;
  Writeln(Return);
  Writeln('');

  Writeln('Press any key...');
  ReadLn;
end.
Das Ergebnis sieht dann so aus:
Code:
{
  "SecondProp": "My second property.",
  "SecondObj": {}
}
anstatt:
Code:
{
  "SecondProp": "My second property.",
  "SecondObj": {
    "FOneProp": 4711,
    "FRefCount": 2
  }
}
Weiß jemand wie ich das Interface Property Serialisieren kann ohne eine Instanzvariable daraus zu machen und mich dann um die Freigabe zu kümmern?
Die Doku von Embarcadero zu TJsonSerializer ist nicht gerade voll mit Beispielen.
Danke schon mal.

himitsu 18. Aug 2017 11:31

AW: Interface mit TJsonSerializer
 
JSON (JavaScript Object Notation): Standardmäßig werden halt nur Objekte gestreamt.

Und Interfaces haben "eigentlich" keine Property, sondern nur Methoden (Funktionen und Prozeduren).

mjustin 18. Aug 2017 12:47

AW: Interface mit TJsonSerializer
 
Funktioniert es nicht wenn man die Properties in der konkreten Klasse auch deklariert?

TiGü 18. Aug 2017 13:20

AW: Interface mit TJsonSerializer
 
Zitat:

Zitat von mjustin (Beitrag 1378988)
Funktioniert es nicht wenn man die Properties in der konkreten Klasse auch deklariert?

Nein, da der Serializer nicht Properties serialisiert, sondern Felder der Klassen.
Alle zu serialisierenden Klassen müssen daher zwangsläufig mit F beginnen (Delphi-Standard).

mjustin 18. Aug 2017 16:04

AW: Interface mit TJsonSerializer
 
Zitat:

Zitat von TiGü (Beitrag 1378995)
Zitat:

Zitat von mjustin (Beitrag 1378988)
Funktioniert es nicht wenn man die Properties in der konkreten Klasse auch deklariert?

Nein, da der Serializer nicht Properties serialisiert, sondern Felder der Klassen.
Alle zu serialisierenden Klassen müssen daher zwangsläufig mit F beginnen (Delphi-Standard).

Im Quelltext beginnen die Felder mit dem Srandard-"F":

Delphi-Quellcode:
[JsonName('SecondProp')] [JsonIn]
FSecondProp: string;

[JsonName('SecondObj')] [JsonIn]
FSecondObj: IFooOne;
Mein Vermutung ist daher, dass zusätzlich noch die property Deklarationen wiederholt werden müssen...

TiGü 21. Aug 2017 08:16

AW: Interface mit TJsonSerializer
 
Zitat:

Zitat von mjustin (Beitrag 1379014)
Zitat:

Zitat von TiGü (Beitrag 1378995)
Zitat:

Zitat von mjustin (Beitrag 1378988)
Funktioniert es nicht wenn man die Properties in der konkreten Klasse auch deklariert?

Nein, da der Serializer nicht Properties serialisiert, sondern Felder der Klassen.
Alle zu serialisierenden Klassen müssen daher zwangsläufig mit F beginnen (Delphi-Standard).

Im Quelltext beginnen die Felder mit dem Srandard-"F":

Delphi-Quellcode:
[JsonName('SecondProp')] [JsonIn]
FSecondProp: string;

[JsonName('SecondObj')] [JsonIn]
FSecondObj: IFooOne;
Mein Vermutung ist daher, dass zusätzlich noch die property Deklarationen wiederholt werden müssen...

Nein nein, es ist genau so, wie ich schrieb. Properties sind dem Serializer total egal.

Sowas hier zum Beispiel wird serialisiert.

Delphi-Quellcode:
TMyClass = class
private
  FMyString: string;
  FMyInteger: Integer;
end;
Das man zusätzlich per Attribut den Namen im JSON verändern kann, ist ein anderes Thema.

himitsu 21. Aug 2017 09:35

AW: Interface mit TJsonSerializer
 
Das ist aber grade etwas, was mich bei solchen Serializern ein bissl stört.
Was hat der einfach so in meinen privaten Variablen rumzupfuschen, anstatt meine öffentliche Schittstellen zu nutzen?

Public oder publisched Felder vielleicht, aber Private?


Alle Zeitangaben in WEZ +1. Es ist jetzt 08:46 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz