{*******************************************************}
{                                                       }
{       Tocsg.Json                                      }
{                                                       }
{       Copyright (C) 2020 kkuzil                       }
{                                                       }
{*******************************************************}

unit Tocsg.Json;

interface

uses
  Tocsg.Obj, SysUtils, WinApi.Windows, Rtti, TypInfo,
  superobject; // http://www.progdigy.com/?page_id=6, http://superobject.googlecode.com/svn/trunk/

type
  TValueArray = array of TValue;

  TTgJson = class(TTgObject)
  public
    class function GetDataAsType<T>(O: ISuperObject; const sPath: String = ''): T;

    class function ValueToJsonObject<T>(aValue: T): ISuperObject;
    class function ValueToJsonAsString<T>(aValue: T): String;
  {$IF CompilerVersion > 21}
    class function ArrayToJsonObject<T>(aValues: TArray<T>): ISuperObject;
    class function ArrayToJsonAsString<T>(aValues: TArray<T>): String;
  {$IFEND}
  end;

implementation

uses
  Tocsg.Safe;

{ TTgJson }

class function TTgJson.GetDataAsType<T>(O: ISuperObject; const sPath: String = ''): T;
var
  ctx: TSuperRttiContext;
begin
  Guard(ctx, TSuperRttiContext.Create);
  try
    if sPath = '' then
      Result := ctx.AsType<T>(O)
    else
      Result := ctx.AsType<T>(O[sPath]);
  except
  //
  end;
end;

class function TTgJson.ValueToJsonObject<T>(aValue: T): ISuperObject;
var
  v: TValue;
  ctx: TSuperRttiContext;
begin
  v := TValue.From<T>(aValue);
  ctx := TSuperRttiContext.Create;
  try
    Result := ctx.ToJson(v, SO);
  finally
    FreeAndNil(ctx);
  end;
end;

class function TTgJson.ValueToJsonAsString<T>(aValue: T): String;
var
  O: ISuperObject;
begin
  O := ValueToJsonObject<T>(aValue);
//  Result := O.AsString;
  Result := O.AsJson;
end;

{$IF CompilerVersion > 21}
class function TTgJson.ArrayToJsonObject<T>(aValues: TArray<T>): ISuperObject;
var
  v: TValue;
  i, nCnt: Integer;
  ValueArray: TValueArray;
  ctx: TSuperRttiContext;
  rctx: TRttiContext;
  rtype: TRttiType;
begin
  nCnt := Length(aValues);
  SetLength(ValueArray, nCnt);
  rctx := TRttiContext.Create;
  try
    for i := 0 to nCnt - 1 do
      ValueArray[i] := TValue.From<T>(aValues[i]);
    rtype := rctx.GetType(TypeInfo(TArray<T>));
    v := TValue.FromArray(rtype.Handle, ValueArray);
    Guard(ctx, TSuperRttiContext.Create);
    Result := ctx.ToJson(v, SO);
  finally
    rctx.Free;
    SetLength(ValueArray, 0);
  end;
end;

class function TTgJson.ArrayToJsonAsString<T>(aValues: TArray<T>): String;
var
  O: ISuperObject;
begin
  O := ArrayToJsonObject<T>(aValues);
  Result := O.AsString;
end;
{$IFEND}

end.
