gale 1 vuosi sitten
vanhempi
commit
6308783498
7 muutettua tiedostoa jossa 2316 lisäystä ja 2 poistoa
  1. 175 2
      README.md
  2. 769 0
      rjson.pas
  3. 47 0
      test/FormMainUnit.fmx
  4. 109 0
      test/FormMainUnit.pas
  5. 20 0
      test/rjson_test.dpr
  6. 1196 0
      test/rjson_test.dproj
  7. BIN
      test/rjson_test.res

+ 175 - 2
README.md

@@ -1,2 +1,175 @@
-# rjson
-Delphi JSON common operation encapsulation JSON鏁版嵁璇诲啓灏佽�
+# JSON common operation encapsulation
+  JSON数据读写封装
+- v0.9.1
+- 2024-09-05 by gale
+- https://github.com/higale/rjson
+
+## Properties:
+- Items[Path] 路径读写,对Object和Array都有效
+
+        a['x.y[2].z'] := 5;
+        b['[3].ok'] := false;
+
+- Items[Index] 数组读写
+
+        a[3][1] := 'hello';
+
+- Pairs[Index] 获取JSONObject下的键值对
+
+        for var i := 0 to RJ.Count do
+        begin
+            Memo1.Lines.Add(RJ.Pairs[i].Key + '=' + RJ.Pairs[i].Format(0));
+        end;
+
+- Count  Object或Array包含条目数,其它类型返回0
+- Index  条目在Array中的索引值,不是数组数条目据返回-1
+- Key    如果是键值对数据,返回键值,否则返回空
+- Root   根数据接口
+- Path   值的路径
+- JSONValue 包含的TJSONValue值
+
+## Methods
+- ToStr 转换为字符串,缺省为空
+
+        var str: string;
+
+        str := RJ['title'];
+        str := RJ['title'].ToStr;
+        str := RJ['title'].ToStr('没有标题');
+
+- ToInt 转换为整数,缺省为0
+
+        var i: integer;
+
+        i := RJ['num'];
+        i := RJ['num'].ToInt;
+        i := RJ['num'].ToInt(-1);
+
+
+- ToInt64 转换为64位整数,缺省为0
+
+        var i64: Int64;
+
+        i64 := RJ['num64'];
+        i64 := RJ['num64'].ToInt64;
+        i64 := RJ['num64'].ToInt64(-1);
+
+- ToFloat 转换为浮点数(使用 Extended),缺省为0.0
+
+        var f: Extended;
+
+        f := RJ['num'];
+        f := RJ['num'].ToFloat;
+        f := RJ['num'].ToFloat(100.0);
+
+- ToBool 转换为 Boolean,缺省为 False
+
+        var b:Boolean;
+
+        b := RJ['bool'];
+        b := RJ['bool'].ToBool;
+        b := RJ['bool'].ToBool(True);
+
+- RootIs<T: TJSONValue> 根是否是某种类型(TJSONObject、TJSONArray等)
+- ValueIs<T: TJSONValue> 当前值是否是某种类型(TJSONObject、TJSONArray等)
+- CloneJSONValue 克隆一份当前值,如果当前值不存在,则生成 TJSONNull
+- Reset 复位到出厂状态
+- Format 输出格式化好的JSON字符串
+
+        str1 := RJ.Format(2); // 缩进2个空格(缺省4个)
+        str2 := RJ.Format(0); // 压缩格式,无缩进无换行
+
+- ParseJSONValue 从字符串加载数据
+
+        RJ.ParseJSONValue('{"a":1}');
+
+- LoadFromFile 从文件加载数据
+
+        procedure LoadFromFile(
+            const AFileName: string;   // JSON文件名
+            AUseBool: boolean = False; // 遇到JSON数据中的 true 或 false 时,是否创建 TJSONBool 类型的值
+            ARaiseExc: boolean = False // 遇到无效的 JSON 数据时是否抛出异常
+        );
+
+- SaveToFile 保存到文件
+
+        procedure aveToFile(
+            const AFileName: string;            // 文件名
+            AIndentation: Integer = 4;          // 缩进空格数,0:不缩进不换行
+            AWriteBOM: boolean = False;         // 文件是否添加 BOM 标记
+            ATrailingLineBreak: boolean = False // 是否在结尾添加一个空行
+        );
+
+## Example:
+    procedure TFormMain.btnTestClick(Sender: TObject);
+    var
+      RJ, RJ1: TRJSON;
+      fTemp: Extended;
+    begin
+      RJ['title'] := 'hello world! 你好,世界!';
+      RJ['a.num'] := 1;
+      RJ['a.hah'] := false;
+      RJ['b[2]'] := 505;
+      RJ['b[0]'] := 'first';
+      RJ['good'] := True;
+      RJ1 := RJ['c'];
+      RJ1['c1'] := 1.1;
+      RJ1['c2[2]'] := 2.33;
+      with RJ['x'] do
+      begin
+        items[1] := 100;
+        items[2] := '202';
+      end;
+      with RJ['y'] do
+      begin
+        items['ya'] := 'y1';
+        items['yb'] := -2;;
+      end;
+      Memo1.Text := RJ.Format;
+      Memo1.Lines.Add('-----------------------------------------------------------');
+      fTemp := RJ['c.c2[3]'];
+      Memo1.Lines.Add('fTemp:' + fTemp.ToString);
+      fTemp := RJ['c.c3[3]'].ToFloat(-100);
+      Memo1.Lines.Add('fTemp:' + fTemp.ToString);
+      Memo1.Lines.Add(RJ['a.num'].ToStr('a.num not exist'));
+      Memo1.Lines.Add(RJ['none'].ToFloat(-1).ToString);
+      Memo1.Lines.Add(RJ['none.a3'].ToStr('none.a3 not exist'));
+      RJ.SaveToFile('test.json', 0);
+    end;
+
+    procedure TFormMain.btnOpenClick(Sender: TObject);
+    var
+      RJ: TRJSON;
+      strTmp: string;
+    begin
+      RJ.LoadFromFile('test.json');
+      Memo1.Text := RJ.Format(8);
+      Memo1.Lines.Add('-----------------------ROOT--------------------------');
+      for var item in RJ do
+      begin
+        strTmp := Format('Index: %d  Key: %s  Value: %s',
+          [item.Index, item.Key, item.Format(0)]);
+        Memo1.Lines.Add(strTmp);
+      end;
+      Memo1.Lines.Add('-----------------------RJ[''a'']--------------------------');
+      for var item in RJ['a'] do
+      begin
+        strTmp := Format('Index: %d  Key: %s  Value: %s',
+          [item.Index, item.Key, item.Format(0)]);
+        Memo1.Lines.Add(strTmp);
+      end;
+      Memo1.Lines.Add('-----------------------RJ[''b'']--------------------------');
+      for var item in RJ['b'] do
+      begin
+        strTmp := Format('Index: %d  Key: %s  Value: %s',
+          [item.Index, item.Key, item.Format(0)]);
+        Memo1.Lines.Add(strTmp);
+      end;
+      Memo1.Lines.Add('-----------------------RJ[''c'']--------------------------');
+      for var i := 0 to RJ['c'].Count - 1 do
+      begin
+        strTmp := Format('Index: %d  Key: %s  Value: %s',
+          [RJ['c'].Pairs[i].Index, RJ['c'].Pairs[i].Key, RJ['c'].Pairs[i].Format(0)]);
+        Memo1.Lines.Add(strTmp);
+      end;
+    end;

+ 769 - 0
rjson.pas

@@ -0,0 +1,769 @@
+(*
+# Delphi JSON common operation encapsulation JSON数据读写封装
+- v0.9.1
+- 2024-09-05 by gale
+- https://github.com/higale/rjson
+
+## Properties:
+- Items[Path] 路径读写,对Object和Array都有效
+
+        a['x.y[2].z'] := 5;
+        b['[3].ok'] := false;
+
+- Items[Index] 数组读写
+
+        a[3][1] := 'hello';
+
+- Pairs[Index] 获取JSONObject下的键值对
+
+        for var i := 0 to RJ.Count do
+        begin
+            Memo1.Lines.Add(RJ.Pairs[i].Key + '=' + RJ.Pairs[i].Format(0));
+        end;
+
+- Count  Object或Array包含条目数,其它类型返回0
+- Index  条目在Array中的索引值,不是数组数条目据返回-1
+- Key    如果是键值对数据,返回键值,否则返回空
+- Root   根数据接口
+- Path   值的路径
+- JSONValue 包含的TJSONValue值
+
+## Methods
+- ToStr 转换为字符串,缺省为空
+
+        var str: string;
+
+        str := RJ['title'];
+        str := RJ['title'].ToStr;
+        str := RJ['title'].ToStr('没有标题');
+
+- ToInt 转换为整数,缺省为0
+
+        var i: integer;
+
+        i := RJ['num'];
+        i := RJ['num'].ToInt;
+        i := RJ['num'].ToInt(-1);
+
+
+- ToInt64 转换为64位整数,缺省为0
+
+        var i64: Int64;
+
+        i64 := RJ['num64'];
+        i64 := RJ['num64'].ToInt64;
+        i64 := RJ['num64'].ToInt64(-1);
+
+- ToFloat 转换为浮点数(使用 Extended),缺省为0.0
+
+        var f: Extended;
+
+        f := RJ['num'];
+        f := RJ['num'].ToFloat;
+        f := RJ['num'].ToFloat(100.0);
+
+- ToBool 转换为 Boolean,缺省为 False
+
+        var b:Boolean;
+
+        b := RJ['bool'];
+        b := RJ['bool'].ToBool;
+        b := RJ['bool'].ToBool(True);
+
+- RootIs<T: TJSONValue> 根是否是某种类型(TJSONObject、TJSONArray等)
+- ValueIs<T: TJSONValue> 当前值是否是某种类型(TJSONObject、TJSONArray等)
+- CloneJSONValue 克隆一份当前值,如果当前值不存在,则生成 TJSONNull
+- Reset 复位到出厂状态
+- Format 输出格式化好的JSON字符串
+
+        str1 := RJ.Format(2); // 缩进2个空格(缺省4个)
+        str2 := RJ.Format(0); // 压缩格式,无缩进无换行
+
+- ParseJSONValue 从字符串加载数据
+
+        RJ.ParseJSONValue('{"a":1}');
+
+- LoadFromFile 从文件加载数据
+
+        procedure LoadFromFile(
+            const AFileName: string;   // JSON文件名
+            AUseBool: boolean = False; // 遇到JSON数据中的 true 或 false 时,是否创建 TJSONBool 类型的值
+            ARaiseExc: boolean = False // 遇到无效的 JSON 数据时是否抛出异常
+        );
+
+- SaveToFile 保存到文件
+
+        procedure aveToFile(
+            const AFileName: string;            // 文件名
+            AIndentation: Integer = 4;          // 缩进空格数,0:不缩进不换行
+            AWriteBOM: boolean = False;         // 文件是否添加 BOM 标记
+            ATrailingLineBreak: boolean = False // 是否在结尾添加一个空行
+        );
+
+## Example:
+    procedure TFormMain.btnTestClick(Sender: TObject);
+    var
+      RJ, RJ1: TRJSON;
+      fTemp: Extended;
+    begin
+      RJ['title'] := 'hello world! 你好,世界!';
+      RJ['a.num'] := 1;
+      RJ['a.hah'] := false;
+      RJ['b[2]'] := 505;
+      RJ['b[0]'] := 'first';
+      RJ['good'] := True;
+      RJ1 := RJ['c'];
+      RJ1['c1'] := 1.1;
+      RJ1['c2[2]'] := 2.33;
+      with RJ['x'] do
+      begin
+        items[1] := 100;
+        items[2] := '202';
+      end;
+      with RJ['y'] do
+      begin
+        items['ya'] := 'y1';
+        items['yb'] := -2;;
+      end;
+      Memo1.Text := RJ.Format;
+      Memo1.Lines.Add('-----------------------------------------------------------');
+      fTemp := RJ['c.c2[3]'];
+      Memo1.Lines.Add('fTemp:' + fTemp.ToString);
+      fTemp := RJ['c.c3[3]'].ToFloat(-100);
+      Memo1.Lines.Add('fTemp:' + fTemp.ToString);
+      Memo1.Lines.Add(RJ['a.num'].ToStr('a.num not exist'));
+      Memo1.Lines.Add(RJ['none'].ToFloat(-1).ToString);
+      Memo1.Lines.Add(RJ['none.a3'].ToStr('none.a3 not exist'));
+      RJ.SaveToFile('test.json', 0);
+    end;
+
+    procedure TFormMain.btnOpenClick(Sender: TObject);
+    var
+      RJ: TRJSON;
+      strTmp: string;
+    begin
+      RJ.LoadFromFile('test.json');
+      Memo1.Text := RJ.Format(8);
+      Memo1.Lines.Add('-----------------------ROOT--------------------------');
+      for var item in RJ do
+      begin
+        strTmp := Format('Index: %d  Key: %s  Value: %s',
+          [item.Index, item.Key, item.Format(0)]);
+        Memo1.Lines.Add(strTmp);
+      end;
+      Memo1.Lines.Add('-----------------------RJ[''a'']--------------------------');
+      for var item in RJ['a'] do
+      begin
+        strTmp := Format('Index: %d  Key: %s  Value: %s',
+          [item.Index, item.Key, item.Format(0)]);
+        Memo1.Lines.Add(strTmp);
+      end;
+      Memo1.Lines.Add('-----------------------RJ[''b'']--------------------------');
+      for var item in RJ['b'] do
+      begin
+        strTmp := Format('Index: %d  Key: %s  Value: %s',
+          [item.Index, item.Key, item.Format(0)]);
+        Memo1.Lines.Add(strTmp);
+      end;
+      Memo1.Lines.Add('-----------------------RJ[''c'']--------------------------');
+      for var i := 0 to RJ['c'].Count - 1 do
+      begin
+        strTmp := Format('Index: %d  Key: %s  Value: %s',
+          [RJ['c'].Pairs[i].Index, RJ['c'].Pairs[i].Key, RJ['c'].Pairs[i].Format(0)]);
+        Memo1.Lines.Add(strTmp);
+      end;
+    end;
+*)
+unit rjson;
+
+interface
+
+uses
+  System.IOUtils, System.Classes, System.SysUtils, System.StrUtils, System.JSON,
+  System.Generics.Collections;
+
+type
+  TJO = TJSONObject;
+  TJA = TJSONArray;
+  TJV = TJSONValue;
+  TJSONValueType = type of TJSONValue;
+  TRJSONEnumerator = class;
+
+  { JSON root data interface }
+  IRJSONRoot = interface
+    function GetData: TJSONValue;
+    procedure SetData(const AValue: TJSONValue);
+    function ForceJV(AType: TJSONValueType): TJSONValue;
+    property Data: TJSONValue read GetData write SetData;
+  end;
+
+  { JSON root data interface class }
+  TRJSONRoot = class(TInterfacedObject, IRJSONRoot)
+  private
+    FData: TJSONValue;
+    function GetData: TJSONValue;
+    procedure SetData(const AValue: TJSONValue);
+    function ForceJV(AType: TJSONValueType): TJSONValue;
+  public
+    constructor Create; overload;
+    constructor Create(const AValue: TJSONValue); overload;
+    destructor Destroy; override;
+  end;
+
+  { JSON data operation structure }
+  TRJSON = record
+  private
+    FRoot: IRJSONRoot;
+    FPath: string;
+    function LinkPath(const ALeft, ARight: string): string;
+    function GetJSONValue: TJSONValue; inline;
+    function GetItems(const APath: string): TRJSON; overload;
+    function GetItems(AIndex: Integer): TRJSON; overload; inline;
+    function GetPairs(AIndex: Integer): TRJSON;
+    procedure SetValue(const [ref] AValue: TRJSON);
+    procedure SetItems(const APath: string; const [ref] AValue: TRJSON); overload;
+    procedure SetItems(AIndex: Integer; const [ref] AValue: TRJSON); overload; inline;
+    function GetCount: Integer;
+    function GetIndex: Integer;
+    function GetKey: string;
+  public
+    function GetEnumerator(): TRJSONEnumerator;
+    class operator Initialize(out Dest: TRJSON);
+    class operator Finalize(var Dest: TRJSON);
+    class operator Assign(var Dest: TRJSON; const [ref] Src: TRJSON);
+    class operator Implicit(const Value: string): TRJSON;
+    class operator Implicit(const [ref] Value: TRJSON): string;
+    class operator Implicit(Value: Integer): TRJSON;
+    class operator Implicit(const [ref] Value: TRJSON): Integer;
+    class operator Implicit(Value: Int64): TRJSON;
+    class operator Implicit(const [ref] Value: TRJSON): Int64;
+    class operator Implicit(Value: Extended): TRJSON;
+    class operator Implicit(const [ref] Value: TRJSON): Extended;
+    class operator Implicit(Value: boolean): TRJSON;
+    class operator Implicit(const [ref] Value: TRJSON): boolean;
+    class operator Implicit(const Value: TJSONValue): TRJSON;
+
+    function ToStr(const ADefault: string = ''): string;
+    function ToInt(ADefault: Integer = 0): Integer;
+    function ToInt64(ADefault: Int64 = 0): Int64;
+    function ToFloat(ADefault: Extended = 0.0): Extended;
+    function ToBool(ADefault: boolean = False): boolean;
+    property Items[const APath: string]: TRJSON read GetItems write SetItems; default;
+    property Items[AIndex: Integer]: TRJSON read GetItems write SetItems; default;
+    property Pairs[AIndex: Integer]: TRJSON read GetPairs;
+    property Count: Integer read GetCount;
+    property Index: Integer read GetIndex;
+    property Key: string read GetKey;
+    property Root: IRJSONRoot read FRoot;
+    property Path: string read FPath;
+    function RootIs<T: TJSONValue>: boolean;
+    function ValueIs<T: TJSONValue>: boolean;
+    property JSONValue: TJSONValue read GetJSONValue;
+    function CloneJSONValue: TJSONValue;
+    procedure Reset;
+    function Format(Indentation: Integer = 4): string;
+    procedure ParseJSONValue(const AData: string; AUseBool: boolean = False; ARaiseExc: boolean = False);
+    procedure LoadFromFile(const AFileName: string; AUseBool: boolean = False; ARaiseExc: boolean = False);
+    procedure SaveToFile(const AFileName: string; AIndentation: Integer = 4; AWriteBOM: boolean = False; ATrailingLineBreak: boolean = False);
+  end;
+
+  { Iterators }
+  TRJSONEnumerator = class
+  private
+    FPData: ^TRJSON;
+    FIndex: Integer;
+    function GetCurrent: TRJSON;
+  public
+    constructor Create(const [ref] AData: TRJSON);
+    function MoveNext: boolean;
+    property Current: TRJSON read GetCurrent;
+  end;
+
+implementation
+
+{ ============================================================================ }
+{ TRJSONRoot }
+
+constructor TRJSONRoot.Create;
+begin
+  inherited;
+  FData := nil;
+end;
+
+constructor TRJSONRoot.Create(const AValue: TJSONValue);
+begin
+  inherited Create;
+  FData := AValue;
+end;
+
+destructor TRJSONRoot.Destroy;
+begin
+  FData.Free;
+  inherited;
+end;
+
+function TRJSONRoot.GetData: TJSONValue;
+begin
+  Result := FData;
+end;
+
+procedure TRJSONRoot.SetData(const AValue: TJSONValue);
+begin
+  FData := AValue;
+end;
+
+function TRJSONRoot.ForceJV(AType: TJSONValueType): TJSONValue;
+begin
+  if not(FData is AType) then
+  begin
+    FData.Free;
+    FData := AType.Create;
+  end;
+  Result := FData;
+end;
+
+{ TRJSONRoot }
+{ ============================================================================ }
+{ TJSONValueHelper }
+
+type
+  TJSONValueHelper = class helper for TJSONValue
+  private
+    procedure ObjSetItem(const AName: string; const AValue: TJSONValue);
+    procedure ArrFill<T: TJSONValue>(ACount: Integer);
+    procedure ArrInsert(const AIndex: Integer; const AValue: TJSONValue);
+    procedure ArrSetItem(AIndex: Integer; const AValue: TJSONValue);
+    function ToType<T>(ADefault: T): T;
+    function GetOrCreate<T: TJSONValue>(AName: string): T;
+    procedure SetValue(const APath: string; const AValue: TJSONValue);
+  end;
+
+procedure TJSONValueHelper.ObjSetItem(const AName: string; const AValue: TJSONValue);
+var
+  pairTmp: TJSONPair;
+begin
+  pairTmp := TJSONObject(self).Get(AName);
+  if pairTmp = nil then
+    TJSONObject(self).AddPair(AName, AValue)
+  else
+    pairTmp.JSONValue := AValue;
+end;
+
+procedure TJSONValueHelper.ArrFill<T>(ACount: Integer);
+begin
+  for var j := TJSONArray(self).Count to ACount do
+    TJSONArray(self).AddElement(T.Create);
+end;
+
+procedure TJSONValueHelper.ArrInsert(const AIndex: Integer; const AValue: TJSONValue);
+begin
+  TJSONArray(self).AddElement(AValue);
+  for var i := AIndex to TJSONArray(self).Count - 2 do
+    TJSONArray(self).AddElement(TJSONArray(self).Remove(AIndex));
+end;
+
+procedure TJSONValueHelper.ArrSetItem(AIndex: Integer; const AValue: TJSONValue);
+begin
+  ArrFill<TJSONNull>(AIndex - 1);
+  if AIndex <= TJSONArray(self).Count - 1 then
+    TJSONArray(self).Remove(AIndex).Free;
+  ArrInsert(AIndex, AValue);
+end;
+
+procedure TJSONValueHelper.SetValue(const APath: string; const AValue: TJSONValue);
+var
+  LParser: TJSONPathParser;
+  preName: string;
+  jv: TJSONValue;
+begin
+  if APath.IsEmpty then
+    raise Exception.Create('TJSONValueHelper.SetValue: path cannot be empty');
+
+  jv := self;
+  LParser := TJSONPathParser.Create(APath);
+  LParser.NextToken;
+  while true do
+  begin
+    preName := LParser.TokenName;
+    LParser.NextToken;
+    case LParser.Token of
+      TJSONPathParser.TToken.Name:
+        jv := jv.GetOrCreate<TJSONObject>(preName);
+      TJSONPathParser.TToken.ArrayIndex:
+        jv := jv.GetOrCreate<TJSONArray>(preName);
+      TJSONPathParser.TToken.Eof:
+        begin
+          if jv is TJSONObject then
+            jv.ObjSetItem(preName, AValue)
+          else
+            jv.ArrSetItem(preName.ToInteger, AValue);
+          break;
+        end;
+    else
+      raise Exception.Create('TJSONValueHelper.SetValue, LParser.Token Error!');
+    end;
+  end;
+end;
+
+function TJSONValueHelper.ToType<T>(ADefault: T): T;
+begin
+  if self = nil then
+    Exit(ADefault);
+  try
+      Result := AsType<T>;
+  except
+      Result := ADefault;
+  end;
+end;
+
+function TJSONValueHelper.GetOrCreate<T>(AName: string): T;
+begin
+  if self is TJSONObject then
+  begin
+    Result := T(TJSONObject(self).GetValue(AName));
+    if not(Result is T) then
+    begin
+      Result := T.Create;
+      ObjSetItem(AName, Result);
+    end;
+  end
+  else if self is TJSONArray then
+  begin
+    ArrFill<TJSONNull>(AName.ToInteger);
+    Result := T(TJSONArray(self).Items[AName.ToInteger]);
+    if not(Result is T) then
+    begin
+      Result := T.Create;
+      ArrSetItem(AName.ToInteger, Result);
+    end;
+  end
+  else
+  begin
+    raise Exception.Create('GetOrCreate<T> Error, self must be TJO or TJA');
+  end;
+end;
+
+{ TJSONValueHelper }
+{ ============================================================================ }
+{ TRJSONEnumerator }
+
+constructor TRJSONEnumerator.Create(const [ref] AData: TRJSON);
+begin
+  inherited Create;
+  FPData := @AData;
+  FIndex := -1;
+end;
+
+function TRJSONEnumerator.GetCurrent: TRJSON;
+var
+  jvTmp: TJSONValue;
+begin
+  Result.Reset;
+  Result.FRoot := FPData^.FRoot;
+  jvTmp := FPData^.GetJSONValue;
+  if jvTmp is TJSONObject then
+  begin
+    if FPData^.FPath = '' then
+      Result.FPath := TJSONObject(jvTmp).Pairs[FIndex].JsonString.Value
+    else
+      Result.FPath := FPData^.FPath + '.' + TJSONObject(jvTmp).Pairs[FIndex].JsonString.Value;
+  end
+  else if jvTmp is TJSONArray then
+  begin
+    Result.FPath := FPData^.FPath + '[' + FIndex.ToString + ']';
+  end;
+end;
+
+function TRJSONEnumerator.MoveNext: boolean;
+begin
+  Inc(FIndex);
+  Exit(FIndex < FPData^.Count)
+end;
+
+{ TRJSONEnumerator }
+{ ============================================================================ }
+{ TRJSON }
+
+function TRJSON.GetEnumerator(): TRJSONEnumerator;
+begin
+  Result := TRJSONEnumerator.Create(self);
+end;
+
+class operator TRJSON.Initialize(out Dest: TRJSON);
+begin
+  Dest.FRoot := TRJSONRoot.Create;
+  Dest.FPath := '';
+end;
+
+class operator TRJSON.Finalize(var Dest: TRJSON);
+begin
+  Dest.FRoot := nil;
+end;
+
+function TRJSON.LinkPath(const ALeft, ARight: string): string;
+begin
+  if ALeft.IsEmpty then
+    Result := ARight
+  else if ARight.IsEmpty then
+    Result := ALeft
+  else if ARight.StartsWith('[') then
+    Result := ALeft + ARight
+  else
+    Result := ALeft + '.' + ARight;
+end;
+
+function TRJSON.GetJSONValue: TJSONValue;
+begin
+  Result := FRoot.Data.FindValue(FPath);
+end;
+
+function TRJSON.CloneJSONValue: TJSONValue;
+begin
+  Result := GetJSONValue;
+  if Result <> nil then
+    Result := Result.Clone as TJSONValue
+  else
+    Result := TJSONNull.Create;
+end;
+
+class operator TRJSON.Assign(var Dest: TRJSON; const [ref] Src: TRJSON);
+begin
+  if Dest.FPath.IsEmpty then
+  begin
+    Dest.FRoot := Src.FRoot;
+    Dest.FPath := Src.FPath;
+  end
+  else
+  begin
+    Dest.SetValue(Src);
+  end;
+end;
+
+class operator TRJSON.Implicit(const Value: string): TRJSON;
+begin
+  Result.FRoot.Data := TJSONString.Create(Value);
+end;
+
+class operator TRJSON.Implicit(const [ref] Value: TRJSON): string;
+begin
+  Result := Value.ToStr('');
+end;
+
+class operator TRJSON.Implicit(Value: Integer): TRJSON;
+begin
+  Result.FRoot.Data := TJSONNumber.Create(Value);
+end;
+
+class operator TRJSON.Implicit(const [ref] Value: TRJSON): Integer;
+begin
+  Result := Value.ToInt(0);
+end;
+
+class operator TRJSON.Implicit(Value: Int64): TRJSON;
+begin
+  Result.FRoot.Data := TJSONNumber.Create(Value);
+end;
+
+class operator TRJSON.Implicit(const [ref] Value: TRJSON): Int64;
+begin
+  Result := Value.ToInt64(0);
+end;
+
+class operator TRJSON.Implicit(Value: Extended): TRJSON;
+begin
+  Result.FRoot.Data := TJSONNumber.Create(Value);
+end;
+
+class operator TRJSON.Implicit(const [ref] Value: TRJSON): Extended;
+begin
+  Result := Value.ToFloat(0.0);
+end;
+
+class operator TRJSON.Implicit(Value: boolean): TRJSON;
+begin
+  Result.FRoot.Data := TJSONBool.Create(Value);
+end;
+
+class operator TRJSON.Implicit(const [ref] Value: TRJSON): boolean;
+begin
+  Result := Value.ToBool(False);
+end;
+
+class operator TRJSON.Implicit(const Value: TJSONValue): TRJSON;
+begin
+  Result.FRoot.Data := Value;
+end;
+
+function TRJSON.ToStr(const ADefault: string): string;
+begin
+  Result := FRoot.Data.FindValue(FPath).ToType<string>(ADefault);
+end;
+
+function TRJSON.ToInt(ADefault: Integer = 0): Integer;
+begin
+  Result := FRoot.Data.FindValue(FPath).ToType<Integer>(ADefault);
+end;
+
+function TRJSON.ToInt64(ADefault: Int64 = 0): Int64;
+begin
+  Result := FRoot.Data.FindValue(FPath).ToType<Int64>(ADefault);
+end;
+
+function TRJSON.ToFloat(ADefault: Extended = 0.0): Extended;
+begin
+  Result := FRoot.Data.FindValue(FPath).ToType<Extended>(ADefault);
+end;
+
+function TRJSON.ToBool(ADefault: boolean = False): boolean;
+begin
+  Result := FRoot.Data.FindValue(FPath).ToType<boolean>(ADefault);
+end;
+
+function TRJSON.GetItems(const APath: string): TRJSON;
+begin
+  Result.FRoot := FRoot;
+  Result.FPath := LinkPath(FPath, APath);
+end;
+
+function TRJSON.GetItems(AIndex: Integer): TRJSON;
+begin
+  Result := GetItems('[' + AIndex.ToString + ']');
+end;
+
+function TRJSON.GetPairs(AIndex: Integer): TRJSON;
+var
+  jvTmp: TJSONValue;
+begin
+  jvTmp := GetJSONValue;
+  if (jvTmp is TJSONObject) then
+    Result := GetItems(TJSONObject(jvTmp).Pairs[AIndex].JsonString.Value);
+end;
+
+procedure TRJSON.SetValue(const [ref] AValue: TRJSON);
+var
+  LValue: TJSONValue;
+begin
+  if FPath.IsEmpty then
+    raise Exception.Create(' TRJSON.SetValue: Path is empty');
+
+  LValue := AValue.CloneJSONValue;
+  try
+    if FPath.StartsWith('[') then
+      FRoot.ForceJV(TJSONArray).SetValue(FPath, LValue)
+    else
+      FRoot.ForceJV(TJSONObject).SetValue(FPath, LValue);
+  except
+    on E: Exception do
+    begin
+      LValue.Free;
+      raise Exception.Create(E.message);
+    end;
+  end;
+
+end;
+
+procedure TRJSON.SetItems(const APath: string; const [ref] AValue: TRJSON);
+var
+  tmp: TRJSON;
+begin
+  tmp.FRoot := FRoot;
+  tmp.FPath := LinkPath(FPath, APath);
+  tmp.SetValue(AValue)
+end;
+
+procedure TRJSON.SetItems(AIndex: Integer; const [ref] AValue: TRJSON);
+begin
+  SetItems('[' + AIndex.ToString + ']', AValue);
+end;
+
+function TRJSON.GetCount: Integer;
+var
+  jvTemp: TJSONValue;
+begin
+  jvTemp := GetJSONValue;
+  if jvTemp is TJSONArray then
+    Result := TJSONArray(jvTemp).Count
+  else if jvTemp is TJSONObject then
+    Result := TJSONObject(jvTemp).Count
+  else
+    Result := 0;
+end;
+
+function TRJSON.GetIndex: Integer;
+var
+  strTmp: string;
+begin
+  Result := -1;
+  strTmp := FPath.Substring(FPath.LastIndexOf('[') + 1);
+  if strTmp.EndsWith(']') then
+    Result := StrToIntDef(strTmp.TrimRight([']']), -1);
+end;
+
+function TRJSON.GetKey: string;
+begin
+  Result := FPath.Substring(FPath.LastIndexOf('.') + 1);
+  if Result.EndsWith(']') then
+    Result := '';
+end;
+
+function TRJSON.RootIs<T>: boolean;
+begin
+  Result := FRoot.Data is T;
+end;
+
+function TRJSON.ValueIs<T>: boolean;
+begin
+  Result := GetJSONValue is T;
+end;
+
+procedure TRJSON.Reset;
+begin
+  FRoot := TRJSONRoot.Create;
+  FPath := '';
+end;
+
+function TRJSON.Format(Indentation: Integer): string;
+var
+  LValue: TJSONValue;
+begin
+  Result := '';
+  LValue := GetJSONValue;
+  if LValue <> nil then
+  begin
+    if Indentation > 0 then
+      Result := LValue.Format(Indentation)
+    else
+      Result := LValue.ToString;
+  end;
+end;
+
+procedure TRJSON.ParseJSONValue(const AData: string; AUseBool: boolean; ARaiseExc: boolean);
+begin
+  Reset;
+  FRoot.Data := TJSONValue.ParseJSONValue(AData, AUseBool, ARaiseExc);
+end;
+
+procedure TRJSON.LoadFromFile(const AFileName: string; AUseBool: boolean; ARaiseExc: boolean);
+begin
+  ParseJSONValue(TFile.ReadAllText(AFileName, TEncoding.UTF8), AUseBool, ARaiseExc);
+end;
+
+procedure TRJSON.SaveToFile(const AFileName: string; AIndentation: Integer; AWriteBOM: boolean; ATrailingLineBreak: boolean);
+var
+  strs: TStrings;
+begin
+  strs := TStringList.Create;
+  try
+    strs.WriteBOM := AWriteBOM;
+    strs.TrailingLineBreak := ATrailingLineBreak;
+    strs.Text := Format(AIndentation);
+    strs.SaveToFile(AFileName, TEncoding.UTF8);
+  finally
+      strs.Free;
+  end;
+end;
+
+{ TRJSON }
+{ ============================================================================ }
+
+end.

+ 47 - 0
test/FormMainUnit.fmx

@@ -0,0 +1,47 @@
+object FormMain: TFormMain
+  Left = 0
+  Top = 0
+  Caption = 'IJO test'
+  ClientHeight = 726
+  ClientWidth = 754
+  Position = ScreenCenter
+  FormFactor.Width = 320
+  FormFactor.Height = 480
+  FormFactor.Devices = [Desktop]
+  DesignerMasterStyle = 0
+  object Memo1: TMemo
+    Touch.InteractiveGestures = [Pan, LongTap, DoubleTap]
+    DataDetectorTypes = []
+    StyledSettings = [Size, Style, FontColor]
+    TextSettings.Font.Family = #23435#20307
+    Anchors = [akLeft, akTop, akRight, akBottom]
+    Position.X = 8.000000000000000000
+    Position.Y = 8.000000000000000000
+    Size.Width = 649.000000000000000000
+    Size.Height = 710.000000000000000000
+    Size.PlatformDefault = False
+    TabOrder = 0
+    Viewport.Width = 645.000000000000000000
+    Viewport.Height = 706.000000000000000000
+  end
+  object btnTest: TButton
+    Position.X = 665.000000000000000000
+    Position.Y = 16.000000000000000000
+    TabOrder = 1
+    Text = 'btnTest'
+    TextSettings.Trimming = None
+    OnClick = btnTestClick
+  end
+  object btnOpen: TButton
+    Position.X = 665.000000000000000000
+    Position.Y = 92.000000000000000000
+    TabOrder = 3
+    Text = 'btnOpen'
+    TextSettings.Trimming = None
+    OnClick = btnOpenClick
+  end
+  object dlgOpen: TOpenDialog
+    Left = 344
+    Top = 176
+  end
+end

+ 109 - 0
test/FormMainUnit.pas

@@ -0,0 +1,109 @@
+unit FormMainUnit;
+
+interface
+
+uses
+  rjson,
+  // System.JSON,
+  // System.rtti,
+  system.StrUtils,
+  system.SysUtils, system.Types, system.UITypes, system.Classes, system.Variants,
+  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Memo.Types,
+  FMX.StdCtrls, FMX.Controls.Presentation, FMX.ScrollBox, FMX.Memo, FMX.Ani;
+
+type
+  TFormMain = class(TForm)
+    Memo1: TMemo;
+    btnTest: TButton;
+    btnOpen: TButton;
+    dlgOpen: TOpenDialog;
+    procedure btnTestClick(Sender: TObject);
+    procedure btnOpenClick(Sender: TObject);
+  private
+
+  public
+    { Public declarations }
+  end;
+
+var
+  FormMain: TFormMain;
+
+implementation
+
+{$R *.fmx}
+
+
+procedure TFormMain.btnTestClick(Sender: TObject);
+var
+  RJ, RJ1: TRJSON;
+  fTemp: Extended;
+begin
+  RJ['title'] := 'hello world! 你好,世界!';
+  RJ['a.num'] := 1;
+  RJ['a.hah'] := false;
+  RJ['b[2]'] := 505;
+  RJ['b[0]'] := 'first';
+  RJ['good'] := True;
+  RJ1 := RJ['c'];
+  RJ1['c1'] := 1.1;
+  RJ1['c2[2]'] := 2.33;
+  with RJ['x'] do
+  begin
+    items[1] := 100;
+    items[2] := '202';
+  end;
+  with RJ['y'] do
+  begin
+    items['ya'] := 'y1';
+    items['yb'] := -2;;
+  end;
+  Memo1.Text := RJ.Format;
+  Memo1.Lines.Add('-----------------------------------------------------------');
+  fTemp := RJ['c.c2[3]'];
+  Memo1.Lines.Add('fTemp:' + fTemp.ToString);
+  fTemp := RJ['c.c3[3]'].ToFloat(-100);
+  Memo1.Lines.Add('fTemp:' + fTemp.ToString);
+  Memo1.Lines.Add(RJ['a.num'].ToStr('a.num not exist'));
+  Memo1.Lines.Add(RJ['none'].ToFloat(-1).ToString);
+  Memo1.Lines.Add(RJ['none.a3'].ToStr('none.a3 not exist'));
+  RJ.SaveToFile('test.json', 0);
+end;
+
+procedure TFormMain.btnOpenClick(Sender: TObject);
+var
+  RJ: TRJSON;
+  strTmp: string;
+begin
+  RJ.LoadFromFile('test.json');
+  Memo1.Text := RJ.Format(8);
+  Memo1.Lines.Add('-----------------------ROOT--------------------------');
+  for var item in RJ do
+  begin
+    strTmp := Format('Index: %d  Key: %s  Value: %s',
+      [item.Index, item.Key, item.Format(0)]);
+    Memo1.Lines.Add(strTmp);
+  end;
+  Memo1.Lines.Add('-----------------------RJ[''a'']--------------------------');
+  for var item in RJ['a'] do
+  begin
+    strTmp := Format('Index: %d  Key: %s  Value: %s',
+      [item.Index, item.Key, item.Format(0)]);
+    Memo1.Lines.Add(strTmp);
+  end;
+  Memo1.Lines.Add('-----------------------RJ[''b'']--------------------------');
+  for var item in RJ['b'] do
+  begin
+    strTmp := Format('Index: %d  Key: %s  Value: %s',
+      [item.Index, item.Key, item.Format(0)]);
+    Memo1.Lines.Add(strTmp);
+  end;
+  Memo1.Lines.Add('-----------------------RJ[''c'']--------------------------');
+  for var i := 0 to RJ['c'].Count - 1 do
+  begin
+    strTmp := Format('Index: %d  Key: %s  Value: %s',
+      [RJ['c'].Pairs[i].Index, RJ['c'].Pairs[i].Key, RJ['c'].Pairs[i].Format(0)]);
+    Memo1.Lines.Add(strTmp);
+  end;
+end;
+
+end.

+ 20 - 0
test/rjson_test.dpr

@@ -0,0 +1,20 @@
+program rjson_test;
+
+uses
+  System.StartUpCopy,
+  FMX.Forms,
+  FormMainUnit in 'FormMainUnit.pas' {FormMain},
+  rjson in '..\rjson.pas';
+
+{$R *.res}
+
+
+begin
+{$IFDEF DEBUG}
+  ReportMemoryLeaksOnShutdown := True;
+{$ENDIF}
+  Application.Initialize;
+  Application.CreateForm(TFormMain, FormMain);
+  Application.Run;
+
+end.

+ 1196 - 0
test/rjson_test.dproj

@@ -0,0 +1,1196 @@
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+    <PropertyGroup>
+        <ProjectGuid>{54E16AC0-1FC7-4A0D-B1CA-2D300161A17E}</ProjectGuid>
+        <ProjectVersion>20.1</ProjectVersion>
+        <FrameworkType>FMX</FrameworkType>
+        <Base>True</Base>
+        <Config Condition="'$(Config)'==''">Debug</Config>
+        <Platform Condition="'$(Platform)'==''">Win32</Platform>
+        <TargetedPlatforms>1</TargetedPlatforms>
+        <AppType>Application</AppType>
+        <MainSource>rjson_test.dpr</MainSource>
+        <ProjectName Condition="'$(ProjectName)'==''">rjson_test</ProjectName>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''">
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="('$(Platform)'=='OSX64' and '$(Base)'=='true') or '$(Base_OSX64)'!=''">
+        <Base_OSX64>true</Base_OSX64>
+        <CfgParent>Base</CfgParent>
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="('$(Platform)'=='OSXARM64' and '$(Base)'=='true') or '$(Base_OSXARM64)'!=''">
+        <Base_OSXARM64>true</Base_OSXARM64>
+        <CfgParent>Base</CfgParent>
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="('$(Platform)'=='Win32' and '$(Base)'=='true') or '$(Base_Win32)'!=''">
+        <Base_Win32>true</Base_Win32>
+        <CfgParent>Base</CfgParent>
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="('$(Platform)'=='Win64' and '$(Base)'=='true') or '$(Base_Win64)'!=''">
+        <Base_Win64>true</Base_Win64>
+        <CfgParent>Base</CfgParent>
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Config)'=='Debug' or '$(Cfg_1)'!=''">
+        <Cfg_1>true</Cfg_1>
+        <CfgParent>Base</CfgParent>
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="('$(Platform)'=='Win32' and '$(Cfg_1)'=='true') or '$(Cfg_1_Win32)'!=''">
+        <Cfg_1_Win32>true</Cfg_1_Win32>
+        <CfgParent>Cfg_1</CfgParent>
+        <Cfg_1>true</Cfg_1>
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="('$(Platform)'=='Win64' and '$(Cfg_1)'=='true') or '$(Cfg_1_Win64)'!=''">
+        <Cfg_1_Win64>true</Cfg_1_Win64>
+        <CfgParent>Cfg_1</CfgParent>
+        <Cfg_1>true</Cfg_1>
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Config)'=='Release' or '$(Cfg_2)'!=''">
+        <Cfg_2>true</Cfg_2>
+        <CfgParent>Base</CfgParent>
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="('$(Platform)'=='Win32' and '$(Cfg_2)'=='true') or '$(Cfg_2_Win32)'!=''">
+        <Cfg_2_Win32>true</Cfg_2_Win32>
+        <CfgParent>Cfg_2</CfgParent>
+        <Cfg_2>true</Cfg_2>
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="('$(Platform)'=='Win64' and '$(Cfg_2)'=='true') or '$(Cfg_2_Win64)'!=''">
+        <Cfg_2_Win64>true</Cfg_2_Win64>
+        <CfgParent>Cfg_2</CfgParent>
+        <Cfg_2>true</Cfg_2>
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Base)'!=''">
+        <DCC_DcuOutput>.\$(Platform)\$(Config)</DCC_DcuOutput>
+        <DCC_ExeOutput>.\$(Platform)\$(Config)</DCC_ExeOutput>
+        <DCC_E>false</DCC_E>
+        <DCC_N>false</DCC_N>
+        <DCC_S>false</DCC_S>
+        <DCC_F>false</DCC_F>
+        <DCC_K>false</DCC_K>
+        <DCC_Namespace>System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)</DCC_Namespace>
+        <Icon_MainIcon>$(BDS)\bin\delphi_PROJECTICON.ico</Icon_MainIcon>
+        <Icns_MainIcns>$(BDS)\bin\delphi_PROJECTICNS.icns</Icns_MainIcns>
+        <SanitizedProjectName>rjson_test</SanitizedProjectName>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Base_OSX64)'!=''">
+        <VerInfo_Keys>CFBundleName=$(MSBuildProjectName);CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleVersion=1.0.0;CFBundleShortVersionString=1.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);NSHighResolutionCapable=true;LSApplicationCategoryType=public.app-category.utilities;NSLocationUsageDescription=The reason for accessing the location information of the user;NSContactsUsageDescription=The reason for accessing the contacts;NSCalendarsUsageDescription=The reason for accessing the calendar data;NSRemindersUsageDescription=The reason for accessing the reminders;NSCameraUsageDescription=The reason for accessing the camera;NSMicrophoneUsageDescription=The reason for accessing the microphone;NSMotionUsageDescription=The reason for accessing the accelerometer;NSDesktopFolderUsageDescription=The reason for accessing the Desktop folder;NSDocumentsFolderUsageDescription=The reason for accessing the Documents folder;NSDownloadsFolderUsageDescription=The reason for accessing the Downloads folder;NSNetworkVolumesUsageDescription=The reason for accessing files on a network volume;NSRemovableVolumesUsageDescription=The reason for accessing files on a removable volume;NSSpeechRecognitionUsageDescription=The reason for requesting to send user data to Apple&apos;s speech recognition servers;ITSAppUsesNonExemptEncryption=false;NSBluetoothAlwaysUsageDescription=The reason for accessing the Bluetooth interface</VerInfo_Keys>
+        <BT_BuildType>Debug</BT_BuildType>
+        <VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Base_OSXARM64)'!=''">
+        <VerInfo_Keys>CFBundleName=$(MSBuildProjectName);CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleVersion=1.0.0;CFBundleShortVersionString=1.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);NSHighResolutionCapable=true;LSApplicationCategoryType=public.app-category.utilities;NSLocationUsageDescription=The reason for accessing the location information of the user;NSContactsUsageDescription=The reason for accessing the contacts;NSCalendarsUsageDescription=The reason for accessing the calendar data;NSRemindersUsageDescription=The reason for accessing the reminders;NSCameraUsageDescription=The reason for accessing the camera;NSMicrophoneUsageDescription=The reason for accessing the microphone;NSMotionUsageDescription=The reason for accessing the accelerometer;NSDesktopFolderUsageDescription=The reason for accessing the Desktop folder;NSDocumentsFolderUsageDescription=The reason for accessing the Documents folder;NSDownloadsFolderUsageDescription=The reason for accessing the Downloads folder;NSNetworkVolumesUsageDescription=The reason for accessing files on a network volume;NSRemovableVolumesUsageDescription=The reason for accessing files on a removable volume;NSSpeechRecognitionUsageDescription=The reason for requesting to send user data to Apple&apos;s speech recognition servers;ITSAppUsesNonExemptEncryption=false;NSBluetoothAlwaysUsageDescription=The reason for accessing the Bluetooth interface</VerInfo_Keys>
+        <BT_BuildType>Debug</BT_BuildType>
+        <VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Base_Win32)'!=''">
+        <DCC_UsePackage>DataSnapServer;vclwinx;emshosting;fmx;DbxCommonDriver;vclie;bindengine;VCLRESTComponents;FireDACCommonODBC;DBXMSSQLDriver;IndyIPCommon;emsclient;FireDACCommonDriver;appanalytics;IndyProtocols;vclx;Skia.Package.RTL;dbxcds;vcledge;IndyIPClient;bindcompvclwinx;FmxTeeUI;emsedge;bindcompfmx;DBXFirebirdDriver;inetdb;ibmonitor;FireDACSqliteDriver;DbxClientDriver;FireDACASADriver;Tee;soapmidas;vclactnband;TeeUI;fmxFireDAC;dbexpress;FireDACInfxDriver;DBXMySQLDriver;VclSmp;inet;DataSnapCommon;fmxase;vcltouch;DBXOdbcDriver;dbrtl;FireDACOracleDriver;FireDACDBXDriver;Skia.Package.FMX;fmxdae;TeeDB;FireDACMSAccDriver;CustomIPTransport;FireDACMSSQLDriver;DataSnapIndy10ServerTransport;DataSnapConnectors;DBXInterBaseDriver;vcldsnap;FireDACMongoDBDriver;IndySystem;FireDACTDataDriver;Skia.Package.VCL;vcldb;ibxbindings;vclFireDAC;bindcomp;FireDACCommon;DataSnapServerMidas;FireDACODBCDriver;emsserverresource;IndyCore;RESTBackendComponents;bindcompdbx;rtl;FireDACMySQLDriver;FireDACADSDriver;RESTComponents;DBXSqliteDriver;vcl;adortl;dsnapxml;IndyIPServer;DataSnapClient;DataSnapProviderClient;dsnapcon;DBXSybaseASEDriver;DBXDb2Driver;vclimg;DataSnapFireDAC;emsclientfiredac;FireDACPgDriver;FireDAC;FireDACDSDriver;inetdbxpress;xmlrtl;tethering;ibxpress;bindcompvcl;dsnap;DBXSybaseASADriver;CloudService;DBXOracleDriver;FireDACDb2Driver;DBXInformixDriver;vclib;DataSnapNativeClient;bindcompvclsmp;fmxobj;FMXTee;DatasnapConnectorsFreePascal;soaprtl;soapserver;FireDACIBDriver;$(DCC_UsePackage)</DCC_UsePackage>
+        <DCC_Namespace>Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)</DCC_Namespace>
+        <BT_BuildType>Debug</BT_BuildType>
+        <VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
+        <VerInfo_Keys>CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=</VerInfo_Keys>
+        <VerInfo_Locale>1033</VerInfo_Locale>
+        <Manifest_File>$(BDS)\bin\default_app.manifest</Manifest_File>
+        <UWP_DelphiLogo44>$(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png</UWP_DelphiLogo44>
+        <UWP_DelphiLogo150>$(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png</UWP_DelphiLogo150>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Base_Win64)'!=''">
+        <DCC_UsePackage>DataSnapServer;vclwinx;emshosting;fmx;DbxCommonDriver;vclie;bindengine;VCLRESTComponents;FireDACCommonODBC;DBXMSSQLDriver;IndyIPCommon;emsclient;FireDACCommonDriver;appanalytics;IndyProtocols;vclx;dbxcds;vcledge;IndyIPClient;bindcompvclwinx;FmxTeeUI;emsedge;bindcompfmx;DBXFirebirdDriver;inetdb;ibmonitor;FireDACSqliteDriver;DbxClientDriver;FireDACASADriver;Tee;soapmidas;vclactnband;TeeUI;fmxFireDAC;dbexpress;FireDACInfxDriver;DBXMySQLDriver;VclSmp;inet;DataSnapCommon;fmxase;vcltouch;DBXOdbcDriver;dbrtl;FireDACOracleDriver;FireDACDBXDriver;fmxdae;TeeDB;FireDACMSAccDriver;CustomIPTransport;FireDACMSSQLDriver;DataSnapIndy10ServerTransport;DataSnapConnectors;DBXInterBaseDriver;vcldsnap;FireDACMongoDBDriver;IndySystem;FireDACTDataDriver;Skia.Package.VCL;vcldb;ibxbindings;vclFireDAC;bindcomp;FireDACCommon;DataSnapServerMidas;FireDACODBCDriver;emsserverresource;IndyCore;RESTBackendComponents;bindcompdbx;rtl;FireDACMySQLDriver;FireDACADSDriver;RESTComponents;DBXSqliteDriver;vcl;adortl;dsnapxml;IndyIPServer;DataSnapClient;DataSnapProviderClient;dsnapcon;DBXSybaseASEDriver;DBXDb2Driver;vclimg;DataSnapFireDAC;emsclientfiredac;FireDACPgDriver;FireDAC;FireDACDSDriver;inetdbxpress;xmlrtl;tethering;ibxpress;bindcompvcl;dsnap;DBXSybaseASADriver;CloudService;DBXOracleDriver;FireDACDb2Driver;DBXInformixDriver;vclib;DataSnapNativeClient;bindcompvclsmp;fmxobj;FMXTee;DatasnapConnectorsFreePascal;soaprtl;soapserver;FireDACIBDriver;$(DCC_UsePackage)</DCC_UsePackage>
+        <DCC_Namespace>Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace)</DCC_Namespace>
+        <BT_BuildType>Debug</BT_BuildType>
+        <VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
+        <VerInfo_Keys>CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=</VerInfo_Keys>
+        <VerInfo_Locale>1033</VerInfo_Locale>
+        <Manifest_File>$(BDS)\bin\default_app.manifest</Manifest_File>
+        <UWP_DelphiLogo44>$(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png</UWP_DelphiLogo44>
+        <UWP_DelphiLogo150>$(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png</UWP_DelphiLogo150>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Cfg_1)'!=''">
+        <DCC_Define>DEBUG;$(DCC_Define)</DCC_Define>
+        <DCC_DebugDCUs>true</DCC_DebugDCUs>
+        <DCC_Optimize>false</DCC_Optimize>
+        <DCC_GenerateStackFrames>true</DCC_GenerateStackFrames>
+        <DCC_DebugInfoInExe>true</DCC_DebugInfoInExe>
+        <DCC_RemoteDebug>true</DCC_RemoteDebug>
+        <DCC_IntegerOverflowCheck>true</DCC_IntegerOverflowCheck>
+        <DCC_RangeChecking>true</DCC_RangeChecking>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Cfg_1_Win32)'!=''">
+        <DCC_RemoteDebug>false</DCC_RemoteDebug>
+        <AppDPIAwarenessMode>PerMonitorV2</AppDPIAwarenessMode>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Cfg_1_Win64)'!=''">
+        <AppDPIAwarenessMode>PerMonitorV2</AppDPIAwarenessMode>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Cfg_2)'!=''">
+        <DCC_LocalDebugSymbols>false</DCC_LocalDebugSymbols>
+        <DCC_Define>RELEASE;$(DCC_Define)</DCC_Define>
+        <DCC_SymbolReferenceInfo>0</DCC_SymbolReferenceInfo>
+        <DCC_DebugInformation>0</DCC_DebugInformation>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Cfg_2_Win32)'!=''">
+        <AppDPIAwarenessMode>PerMonitorV2</AppDPIAwarenessMode>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Cfg_2_Win64)'!=''">
+        <AppDPIAwarenessMode>PerMonitorV2</AppDPIAwarenessMode>
+    </PropertyGroup>
+    <ItemGroup>
+        <DelphiCompile Include="$(MainSource)">
+            <MainSource>MainSource</MainSource>
+        </DelphiCompile>
+        <DCCReference Include="FormMainUnit.pas">
+            <Form>FormMain</Form>
+            <FormType>fmx</FormType>
+        </DCCReference>
+        <DCCReference Include="..\rjson.pas"/>
+        <None Include="..\README.md"/>
+        <BuildConfiguration Include="Base">
+            <Key>Base</Key>
+        </BuildConfiguration>
+        <BuildConfiguration Include="Debug">
+            <Key>Cfg_1</Key>
+            <CfgParent>Base</CfgParent>
+        </BuildConfiguration>
+        <BuildConfiguration Include="Release">
+            <Key>Cfg_2</Key>
+            <CfgParent>Base</CfgParent>
+        </BuildConfiguration>
+    </ItemGroup>
+    <ProjectExtensions>
+        <Borland.Personality>Delphi.Personality.12</Borland.Personality>
+        <Borland.ProjectType>Application</Borland.ProjectType>
+        <BorlandProject>
+            <Delphi.Personality>
+                <Source>
+                    <Source Name="MainSource">rjson_test.dpr</Source>
+                </Source>
+            </Delphi.Personality>
+            <Deployment Version="4">
+                <DeployFile LocalName="$(BDS)\Redist\iossimulator\libcgunwind.1.0.dylib" Class="DependencyModule">
+                    <Platform Name="iOSSimulator">
+                        <Overwrite>true</Overwrite>
+                    </Platform>
+                </DeployFile>
+                <DeployFile LocalName="$(BDS)\Redist\iossimulator\libpcre.dylib" Class="DependencyModule">
+                    <Platform Name="iOSSimulator">
+                        <Overwrite>true</Overwrite>
+                    </Platform>
+                </DeployFile>
+                <DeployFile LocalName="$(BDS)\Redist\osx32\libcgunwind.1.0.dylib" Class="DependencyModule">
+                    <Platform Name="OSX32">
+                        <Overwrite>true</Overwrite>
+                    </Platform>
+                </DeployFile>
+                <DeployFile LocalName="$(BDS)\bin\delphi_PROJECTICNS.icns" Configuration="Debug" Class="ProjectOSXResource">
+                    <Platform Name="OSX64">
+                        <RemoteName>JOHelperTest.icns</RemoteName>
+                        <Overwrite>true</Overwrite>
+                    </Platform>
+                </DeployFile>
+                <DeployFile LocalName="..\README.md" Configuration="Debug" Class="ProjectFile">
+                    <Platform Name="Win32">
+                        <RemoteDir>.\</RemoteDir>
+                        <Overwrite>true</Overwrite>
+                    </Platform>
+                </DeployFile>
+                <DeployFile LocalName="OSX64\Debug\JOHelperTest.dSYM" Configuration="Debug" Class="ProjectOSXDebug">
+                    <Platform Name="OSX64">
+                        <RemoteName>JOHelperTest</RemoteName>
+                        <Overwrite>true</Overwrite>
+                    </Platform>
+                </DeployFile>
+                <DeployFile LocalName="OSX64\Debug\JOHelperTest.entitlements" Configuration="Debug" Class="ProjectOSXEntitlements">
+                    <Platform Name="OSX64">
+                        <Overwrite>true</Overwrite>
+                    </Platform>
+                </DeployFile>
+                <DeployFile LocalName="OSX64\Debug\JOHelperTest.info.plist" Configuration="Debug" Class="ProjectOSXInfoPList">
+                    <Platform Name="OSX64">
+                        <RemoteName>Info.plist</RemoteName>
+                        <Overwrite>true</Overwrite>
+                    </Platform>
+                </DeployFile>
+                <DeployFile LocalName="OSX64\Debug\rjson_test" Configuration="Debug" Class="ProjectOutput">
+                    <Platform Name="OSX64">
+                        <RemoteName>rjson_test</RemoteName>
+                        <Overwrite>true</Overwrite>
+                    </Platform>
+                </DeployFile>
+                <DeployFile LocalName="Win32\Debug\rjson_test.exe" Configuration="Debug" Class="ProjectOutput">
+                    <Platform Name="Win32">
+                        <RemoteName>rjson_test.exe</RemoteName>
+                        <Overwrite>true</Overwrite>
+                    </Platform>
+                </DeployFile>
+                <DeployClass Name="AdditionalDebugSymbols">
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="OSX32">
+                        <RemoteDir>Contents\MacOS</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Win32">
+                        <Operation>0</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="AndroidClasses">
+                    <Platform Name="Android">
+                        <RemoteDir>classes</RemoteDir>
+                        <Operation>64</Operation>
+                    </Platform>
+                    <Platform Name="Android64">
+                        <RemoteDir>classes</RemoteDir>
+                        <Operation>64</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="AndroidFileProvider">
+                    <Platform Name="Android">
+                        <RemoteDir>res\xml</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Android64">
+                        <RemoteDir>res\xml</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="AndroidLibnativeArmeabiFile">
+                    <Platform Name="Android">
+                        <RemoteDir>library\lib\armeabi</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Android64">
+                        <RemoteDir>library\lib\armeabi</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="AndroidLibnativeArmeabiv7aFile">
+                    <Platform Name="Android64">
+                        <RemoteDir>library\lib\armeabi-v7a</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="AndroidLibnativeMipsFile">
+                    <Platform Name="Android">
+                        <RemoteDir>library\lib\mips</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Android64">
+                        <RemoteDir>library\lib\mips</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="AndroidServiceOutput">
+                    <Platform Name="Android">
+                        <RemoteDir>library\lib\armeabi-v7a</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Android64">
+                        <RemoteDir>library\lib\arm64-v8a</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="AndroidServiceOutput_Android32">
+                    <Platform Name="Android64">
+                        <RemoteDir>library\lib\armeabi-v7a</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="AndroidSplashImageDef">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Android64">
+                        <RemoteDir>res\drawable</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="AndroidSplashImageDefV21">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-anydpi-v21</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Android64">
+                        <RemoteDir>res\drawable-anydpi-v21</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="AndroidSplashStyles">
+                    <Platform Name="Android">
+                        <RemoteDir>res\values</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Android64">
+                        <RemoteDir>res\values</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="AndroidSplashStylesV21">
+                    <Platform Name="Android">
+                        <RemoteDir>res\values-v21</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Android64">
+                        <RemoteDir>res\values-v21</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="AndroidSplashStylesV31">
+                    <Platform Name="Android">
+                        <RemoteDir>res\values-v31</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Android64">
+                        <RemoteDir>res\values-v31</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_AdaptiveIcon">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-anydpi-v26</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Android64">
+                        <RemoteDir>res\drawable-anydpi-v26</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_AdaptiveIconBackground">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Android64">
+                        <RemoteDir>res\drawable</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_AdaptiveIconForeground">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Android64">
+                        <RemoteDir>res\drawable</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_AdaptiveIconMonochrome">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Android64">
+                        <RemoteDir>res\drawable</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_AdaptiveIconV33">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-anydpi-v33</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Android64">
+                        <RemoteDir>res\drawable-anydpi-v33</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_Colors">
+                    <Platform Name="Android">
+                        <RemoteDir>res\values</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Android64">
+                        <RemoteDir>res\values</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_ColorsDark">
+                    <Platform Name="Android">
+                        <RemoteDir>res\values-night-v21</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Android64">
+                        <RemoteDir>res\values-night-v21</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_DefaultAppIcon">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Android64">
+                        <RemoteDir>res\drawable</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_LauncherIcon144">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-xxhdpi</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Android64">
+                        <RemoteDir>res\drawable-xxhdpi</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_LauncherIcon192">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-xxxhdpi</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Android64">
+                        <RemoteDir>res\drawable-xxxhdpi</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_LauncherIcon36">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-ldpi</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Android64">
+                        <RemoteDir>res\drawable-ldpi</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_LauncherIcon48">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-mdpi</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Android64">
+                        <RemoteDir>res\drawable-mdpi</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_LauncherIcon72">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-hdpi</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Android64">
+                        <RemoteDir>res\drawable-hdpi</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_LauncherIcon96">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-xhdpi</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Android64">
+                        <RemoteDir>res\drawable-xhdpi</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_NotificationIcon24">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-mdpi</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Android64">
+                        <RemoteDir>res\drawable-mdpi</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_NotificationIcon36">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-hdpi</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Android64">
+                        <RemoteDir>res\drawable-hdpi</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_NotificationIcon48">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-xhdpi</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Android64">
+                        <RemoteDir>res\drawable-xhdpi</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_NotificationIcon72">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-xxhdpi</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Android64">
+                        <RemoteDir>res\drawable-xxhdpi</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_NotificationIcon96">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-xxxhdpi</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Android64">
+                        <RemoteDir>res\drawable-xxxhdpi</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_SplashImage426">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-small</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Android64">
+                        <RemoteDir>res\drawable-small</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_SplashImage470">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-normal</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Android64">
+                        <RemoteDir>res\drawable-normal</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_SplashImage640">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-large</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Android64">
+                        <RemoteDir>res\drawable-large</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_SplashImage960">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-xlarge</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Android64">
+                        <RemoteDir>res\drawable-xlarge</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_Strings">
+                    <Platform Name="Android">
+                        <RemoteDir>res\values</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Android64">
+                        <RemoteDir>res\values</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_VectorizedNotificationIcon">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-anydpi-v24</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Android64">
+                        <RemoteDir>res\drawable-anydpi-v24</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_VectorizedSplash">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Android64">
+                        <RemoteDir>res\drawable</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_VectorizedSplashDark">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-night-anydpi-v21</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Android64">
+                        <RemoteDir>res\drawable-night-anydpi-v21</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_VectorizedSplashV31">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-anydpi-v31</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Android64">
+                        <RemoteDir>res\drawable-anydpi-v31</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_VectorizedSplashV31Dark">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-night-anydpi-v31</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Android64">
+                        <RemoteDir>res\drawable-night-anydpi-v31</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="DebugSymbols">
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="OSX32">
+                        <RemoteDir>Contents\MacOS</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Win32">
+                        <Operation>0</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="DependencyFramework">
+                    <Platform Name="OSX32">
+                        <RemoteDir>Contents\MacOS</RemoteDir>
+                        <Operation>1</Operation>
+                        <Extensions>.framework</Extensions>
+                    </Platform>
+                    <Platform Name="OSX64">
+                        <RemoteDir>Contents\MacOS</RemoteDir>
+                        <Operation>1</Operation>
+                        <Extensions>.framework</Extensions>
+                    </Platform>
+                    <Platform Name="OSXARM64">
+                        <RemoteDir>Contents\MacOS</RemoteDir>
+                        <Operation>1</Operation>
+                        <Extensions>.framework</Extensions>
+                    </Platform>
+                    <Platform Name="Win32">
+                        <Operation>0</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="DependencyModule">
+                    <Platform Name="iOSDevice32">
+                        <Operation>1</Operation>
+                        <Extensions>.dylib</Extensions>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>1</Operation>
+                        <Extensions>.dylib</Extensions>
+                    </Platform>
+                    <Platform Name="iOSSimARM64">
+                        <Operation>1</Operation>
+                        <Extensions>.dylib</Extensions>
+                    </Platform>
+                    <Platform Name="OSX32">
+                        <RemoteDir>Contents\MacOS</RemoteDir>
+                        <Operation>1</Operation>
+                        <Extensions>.dylib</Extensions>
+                    </Platform>
+                    <Platform Name="OSX64">
+                        <RemoteDir>Contents\MacOS</RemoteDir>
+                        <Operation>1</Operation>
+                        <Extensions>.dylib</Extensions>
+                    </Platform>
+                    <Platform Name="OSXARM64">
+                        <RemoteDir>Contents\MacOS</RemoteDir>
+                        <Operation>1</Operation>
+                        <Extensions>.dylib</Extensions>
+                    </Platform>
+                    <Platform Name="Win32">
+                        <Operation>0</Operation>
+                        <Extensions>.dll;.bpl</Extensions>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Required="true" Name="DependencyPackage">
+                    <Platform Name="iOSDevice32">
+                        <Operation>1</Operation>
+                        <Extensions>.dylib</Extensions>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>1</Operation>
+                        <Extensions>.dylib</Extensions>
+                    </Platform>
+                    <Platform Name="iOSSimARM64">
+                        <Operation>1</Operation>
+                        <Extensions>.dylib</Extensions>
+                    </Platform>
+                    <Platform Name="OSX32">
+                        <RemoteDir>Contents\MacOS</RemoteDir>
+                        <Operation>1</Operation>
+                        <Extensions>.dylib</Extensions>
+                    </Platform>
+                    <Platform Name="OSX64">
+                        <RemoteDir>Contents\MacOS</RemoteDir>
+                        <Operation>1</Operation>
+                        <Extensions>.dylib</Extensions>
+                    </Platform>
+                    <Platform Name="OSXARM64">
+                        <RemoteDir>Contents\MacOS</RemoteDir>
+                        <Operation>1</Operation>
+                        <Extensions>.dylib</Extensions>
+                    </Platform>
+                    <Platform Name="Win32">
+                        <Operation>0</Operation>
+                        <Extensions>.bpl</Extensions>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="File">
+                    <Platform Name="Android">
+                        <Operation>0</Operation>
+                    </Platform>
+                    <Platform Name="Android64">
+                        <Operation>0</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice32">
+                        <Operation>0</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>0</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimARM64">
+                        <Operation>0</Operation>
+                    </Platform>
+                    <Platform Name="OSX32">
+                        <RemoteDir>Contents\Resources\StartUp\</RemoteDir>
+                        <Operation>0</Operation>
+                    </Platform>
+                    <Platform Name="OSX64">
+                        <RemoteDir>Contents\Resources\StartUp\</RemoteDir>
+                        <Operation>0</Operation>
+                    </Platform>
+                    <Platform Name="OSXARM64">
+                        <RemoteDir>Contents\Resources\StartUp\</RemoteDir>
+                        <Operation>0</Operation>
+                    </Platform>
+                    <Platform Name="Win32">
+                        <Operation>0</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="ProjectAndroidManifest">
+                    <Platform Name="Android">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Android64">
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="ProjectOSXDebug">
+                    <Platform Name="OSX64">
+                        <RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="OSXARM64">
+                        <RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="ProjectOSXEntitlements">
+                    <Platform Name="OSX32">
+                        <RemoteDir>..\</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="OSX64">
+                        <RemoteDir>..\</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="OSXARM64">
+                        <RemoteDir>..\</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="ProjectOSXInfoPList">
+                    <Platform Name="OSX32">
+                        <RemoteDir>Contents</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="OSX64">
+                        <RemoteDir>Contents</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="OSXARM64">
+                        <RemoteDir>Contents</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="ProjectOSXResource">
+                    <Platform Name="OSX32">
+                        <RemoteDir>Contents\Resources</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="OSX64">
+                        <RemoteDir>Contents\Resources</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="OSXARM64">
+                        <RemoteDir>Contents\Resources</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Required="true" Name="ProjectOutput">
+                    <Platform Name="Android">
+                        <RemoteDir>library\lib\armeabi-v7a</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Android64">
+                        <RemoteDir>library\lib\arm64-v8a</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice32">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimARM64">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Linux64">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="OSX32">
+                        <RemoteDir>Contents\MacOS</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="OSX64">
+                        <RemoteDir>Contents\MacOS</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="OSXARM64">
+                        <RemoteDir>Contents\MacOS</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Win32">
+                        <Operation>0</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="ProjectOutput_Android32">
+                    <Platform Name="Android64">
+                        <RemoteDir>library\lib\armeabi-v7a</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="ProjectUWPManifest">
+                    <Platform Name="Win32">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Win64">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Win64x">
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="ProjectiOSDeviceDebug">
+                    <Platform Name="iOSDevice32">
+                        <RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimARM64">
+                        <RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="ProjectiOSEntitlements">
+                    <Platform Name="iOSDevice32">
+                        <RemoteDir>..\</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <RemoteDir>..\</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimARM64">
+                        <RemoteDir>..\</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="ProjectiOSInfoPList">
+                    <Platform Name="iOSDevice32">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimARM64">
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="ProjectiOSLaunchScreen">
+                    <Platform Name="iOSDevice64">
+                        <RemoteDir>..\$(PROJECTNAME).launchscreen</RemoteDir>
+                        <Operation>64</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimARM64">
+                        <RemoteDir>..\$(PROJECTNAME).launchscreen</RemoteDir>
+                        <Operation>64</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="ProjectiOSResource">
+                    <Platform Name="iOSDevice32">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimARM64">
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="UWP_DelphiLogo150">
+                    <Platform Name="Win32">
+                        <RemoteDir>Assets</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Win64">
+                        <RemoteDir>Assets</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="UWP_DelphiLogo44">
+                    <Platform Name="Win32">
+                        <RemoteDir>Assets</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Win64">
+                        <RemoteDir>Assets</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="iOS_AppStore1024">
+                    <Platform Name="iOSDevice64">
+                        <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimARM64">
+                        <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="iPad_AppIcon152">
+                    <Platform Name="iOSDevice64">
+                        <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimARM64">
+                        <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="iPad_AppIcon167">
+                    <Platform Name="iOSDevice64">
+                        <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimARM64">
+                        <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="iPad_Launch2x">
+                    <Platform Name="iOSDevice64">
+                        <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimARM64">
+                        <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="iPad_LaunchDark2x">
+                    <Platform Name="iOSDevice64">
+                        <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimARM64">
+                        <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="iPad_Notification40">
+                    <Platform Name="iOSDevice64">
+                        <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimARM64">
+                        <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="iPad_Setting58">
+                    <Platform Name="iOSDevice64">
+                        <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimARM64">
+                        <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="iPad_SpotLight80">
+                    <Platform Name="iOSDevice64">
+                        <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimARM64">
+                        <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="iPhone_AppIcon120">
+                    <Platform Name="iOSDevice64">
+                        <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimARM64">
+                        <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="iPhone_AppIcon180">
+                    <Platform Name="iOSDevice64">
+                        <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimARM64">
+                        <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="iPhone_Launch2x">
+                    <Platform Name="iOSDevice64">
+                        <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimARM64">
+                        <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="iPhone_Launch3x">
+                    <Platform Name="iOSDevice64">
+                        <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimARM64">
+                        <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="iPhone_LaunchDark2x">
+                    <Platform Name="iOSDevice64">
+                        <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimARM64">
+                        <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="iPhone_LaunchDark3x">
+                    <Platform Name="iOSDevice64">
+                        <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimARM64">
+                        <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="iPhone_Notification40">
+                    <Platform Name="iOSDevice64">
+                        <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimARM64">
+                        <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="iPhone_Notification60">
+                    <Platform Name="iOSDevice64">
+                        <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimARM64">
+                        <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="iPhone_Setting58">
+                    <Platform Name="iOSDevice64">
+                        <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimARM64">
+                        <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="iPhone_Setting87">
+                    <Platform Name="iOSDevice64">
+                        <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimARM64">
+                        <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="iPhone_Spotlight120">
+                    <Platform Name="iOSDevice64">
+                        <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimARM64">
+                        <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="iPhone_Spotlight80">
+                    <Platform Name="iOSDevice64">
+                        <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimARM64">
+                        <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <ProjectRoot Platform="Android" Name="$(PROJECTNAME)"/>
+                <ProjectRoot Platform="Android64" Name="$(PROJECTNAME)"/>
+                <ProjectRoot Platform="iOSDevice32" Name="$(PROJECTNAME).app"/>
+                <ProjectRoot Platform="iOSDevice64" Name="$(PROJECTNAME).app"/>
+                <ProjectRoot Platform="iOSSimARM64" Name="$(PROJECTNAME).app"/>
+                <ProjectRoot Platform="Linux64" Name="$(PROJECTNAME)"/>
+                <ProjectRoot Platform="OSX32" Name="$(PROJECTNAME).app"/>
+                <ProjectRoot Platform="OSX64" Name="$(PROJECTNAME).app"/>
+                <ProjectRoot Platform="OSXARM64" Name="$(PROJECTNAME).app"/>
+                <ProjectRoot Platform="Win32" Name="$(PROJECTNAME)"/>
+                <ProjectRoot Platform="Win64" Name="$(PROJECTNAME)"/>
+                <ProjectRoot Platform="Win64x" Name="$(PROJECTNAME)"/>
+            </Deployment>
+            <Platforms>
+                <Platform value="OSX64">False</Platform>
+                <Platform value="OSXARM64">False</Platform>
+                <Platform value="Win32">True</Platform>
+                <Platform value="Win64">False</Platform>
+            </Platforms>
+        </BorlandProject>
+        <ProjectFileVersion>12</ProjectFileVersion>
+    </ProjectExtensions>
+    <Import Project="$(BDS)\Bin\CodeGear.Delphi.Targets" Condition="Exists('$(BDS)\Bin\CodeGear.Delphi.Targets')"/>
+    <Import Project="$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj" Condition="Exists('$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj')"/>
+    <Import Project="$(MSBuildProjectName).deployproj" Condition="Exists('$(MSBuildProjectName).deployproj')"/>
+</Project>

BIN
test/rjson_test.res