unit Unit1;
interface
uses
System.Generics.Collections,
System.SysUtils,
REST.Json.Types;
type { internal data object }
TFooData =
class
private
FNumber: Integer;
public
property Number: Integer
read FNumber
write FNumber;
end;
type { api objects }
TFooWriteJson =
class
private
[ JsonName( '
number_write' ) ]
FNumber:
string;
public
property Number:
string read FNumber
write FNumber;
end;
TFooReadJson =
class
private
[ JsonName( '
number_read' ) ]
FNumber: Integer;
public
property Number: Integer
read FNumber
write FNumber;
end;
type
TJsonSerializer =
class abstract
private type
TConverter =
record
ClassType: TClass;
Convert: TFunc<TObject, TObject>;
end;
private
FConverterMap: TDictionary<TClass, TConverter>;
FReverterMap : TDictionary<TClass, TConverter>;
protected
procedure RegisterConverter<TSource:
class; TResult:
class>( Converter: TFunc<TSource, TResult> );
procedure RegisterConverterReverter<TSource:
class; TResult:
class,
constructor>( Converter: TFunc<TSource, TResult>; Reverter: TFunc<TResult, TSource> );
procedure RegisterReverter<TSource:
class; TResult:
class,
constructor>( Converter: TFunc<TResult, TSource> );
public
constructor Create;
virtual;
destructor Destroy;
override;
function Serialize<T:
class>( AObject: T ):
string;
function Deserialize<T:
class>(
const JsonStr:
string ): T;
end;
type
TConcreteSerializer =
class( TJsonSerializer )
public
constructor Create;
virtual;
end;
implementation
uses
REST.Json,
System.Json;
{ TJsonSerializer }
constructor TJsonSerializer.Create;
begin
inherited;
FConverterMap := TDictionary<TClass, TConverter>.Create;
FReverterMap := TDictionary<TClass, TConverter>.Create;
end;
function TJsonSerializer.Deserialize<T>(
const JsonStr:
string ): T;
var
lConverter: TConverter;
lJson : TJsonObject;
lSerObj : TObject;
begin
if not FReverterMap.TryGetValue( T, lConverter )
then
raise Exception.Create( '
Fehlermeldung' );
lJson := TJsonObject.ParseJSONValue( JsonStr )
as TJsonObject;
try
lSerObj := lConverter.ClassType.Create;
try
TJson.JsonToObject( lSerObj, lJson );
Result := lConverter.Convert( lSerObj )
as T;
finally
lSerObj.Free;
end;
finally
lJson.Free;
end;
end;
destructor TJsonSerializer.Destroy;
begin
FConverterMap.Free;
FReverterMap.Free;
inherited;
end;
procedure TJsonSerializer.RegisterConverter<TSource, TResult>( Converter: TFunc<TSource, TResult> );
var
lConverter: TConverter;
begin
lConverter.ClassType := TResult;
lConverter.Convert :=
function( Source: TObject ): TObject
begin
Result := Converter( Source
as TSource );
end;
FConverterMap.Add( TSource, lConverter );
end;
procedure TJsonSerializer.RegisterConverterReverter<TSource, TResult>( Converter: TFunc<TSource, TResult>; Reverter: TFunc<TResult, TSource> );
begin
RegisterConverter<TSource, TResult>( Converter );
RegisterReverter<TSource, TResult>( Reverter );
end;
procedure TJsonSerializer.RegisterReverter<TSource, TResult>( Converter: TFunc<TResult, TSource> );
var
lConverter: TConverter;
begin
lConverter.ClassType := TResult;
lConverter.Convert :=
function( Source: TObject ): TObject
begin
Result := Converter( Source
as TResult );
end;
FReverterMap.Add( TSource, lConverter );
end;
function TJsonSerializer.Serialize<T>( AObject: T ):
string;
var
lConverter: TConverter;
lSerObj : TObject;
begin
if not FConverterMap.TryGetValue( AObject.ClassType, lConverter )
then
raise Exception.Create( '
Fehlermeldung' );
lSerObj := lConverter.Convert( AObject );
try
Result := TJson.ObjectToJsonString( lSerObj );
finally
lSerObj.Free;
end;
end;
{ TConcreteSerializer }
constructor TConcreteSerializer.Create;
begin
inherited;
RegisterConverter<TFooData, TFooWriteJson>(
function( s: TFooData ): TFooWriteJson
begin
Result := TFooWriteJson.Create;
Result.Number := IntToStr( s.Number );
end );
RegisterReverter<TFooData, TFooReadJson>(
function( s: TFooReadJson ): TFooData
begin
Result := TFooData.Create;
Result.Number := s.Number;
end );
end;
end.