1
0

rjson.pas 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828
  1. {
  2. TRJ - JSON Simple Read and Write
  3. - v0.9.4
  4. - 2024-09-09 by gale
  5. - https://github.com/higale/RJSON
  6. }
  7. unit rjson;
  8. interface
  9. uses
  10. System.IOUtils, System.Classes, System.SysUtils, System.JSON, System.Generics.Collections;
  11. type
  12. TJObject = TJSONObject;
  13. TJArray = TJSONArray;
  14. TJValue = TJSONValue;
  15. TJString = TJSONString;
  16. TJNumber = TJSONNumber;
  17. TJBool = TJSONBool;
  18. TJNull = TJSONNull;
  19. TJVType = type of TJValue;
  20. IRJRoot = interface
  21. ['{486F1FA6-2CDD-4124-98C5-CE7C398B7143}']
  22. function GetData: TJValue;
  23. procedure SetData(const AValue: TJValue);
  24. function ForceData(AType: TJVType): TJValue;
  25. property Data: TJValue read GetData write SetData;
  26. end;
  27. TRJRoot = class(TInterfacedObject, IRJRoot)
  28. private
  29. FData: TJValue;
  30. function GetData: TJValue;
  31. procedure SetData(const AValue: TJValue);
  32. function ForceData(AType: TJVType): TJValue;
  33. public
  34. constructor Create;
  35. destructor Destroy; override;
  36. end;
  37. TRPath = record
  38. private
  39. FData: string;
  40. public
  41. class operator Implicit(const Value: string): TRPath;
  42. class operator Implicit(Value: Integer): TRPath;
  43. class operator Implicit(const [ref] Value: TRPath): string;
  44. end;
  45. TRJEnumerator = class;
  46. TRJ = record
  47. private
  48. FIRoot: IRJRoot;
  49. FPath: string;
  50. function GetRootRefCount: Integer;
  51. function ForceRootJValue(const APath: string): TJValue;
  52. function LinkPath(const ALeft, ARight: string): string;
  53. function GeTJValue: TJValue; inline;
  54. function GetItems(const APath: TRPath): TRJ;
  55. function GetPairs(AIndex: Integer): TRJ;
  56. procedure SetValue(const [ref] AValue: TRJ);
  57. procedure SetItems(const APath: TRPath; const [ref] AValue: TRJ);
  58. function GetS(const APath: TRPath): string; overload;
  59. procedure SetS(const APath: TRPath; AValue: string); overload;
  60. function GetI(const APath: TRPath): Integer; overload;
  61. procedure SetI(const APath: TRPath; AValue: Integer); overload;
  62. function GetI64(const APath: TRPath): Int64; overload;
  63. procedure SetI64(const APath: TRPath; AValue: Int64); overload;
  64. function GetF(const APath: TRPath): Extended; overload;
  65. procedure SetF(const APath: TRPath; AValue: Extended); overload;
  66. function GetB(const APath: TRPath): boolean; overload;
  67. procedure SetB(const APath: TRPath; AValue: boolean); overload;
  68. function GetCount: Integer;
  69. function GetIndex: Integer;
  70. function GetKey: string;
  71. function GetRoot: TRJ;
  72. public
  73. function GetEnumerator(): TRJEnumerator;
  74. class operator Initialize(out Dest: TRJ);
  75. class operator Finalize(var Dest: TRJ);
  76. class operator Assign(var Dest: TRJ; const [ref] Src: TRJ);
  77. class operator Implicit(const Value: string): TRJ;
  78. class operator Implicit(const [ref] Value: TRJ): string;
  79. class operator Implicit(Value: Integer): TRJ;
  80. class operator Implicit(const [ref] Value: TRJ): Integer;
  81. class operator Implicit(Value: Int64): TRJ;
  82. class operator Implicit(const [ref] Value: TRJ): Int64;
  83. class operator Implicit(Value: Extended): TRJ;
  84. class operator Implicit(const [ref] Value: TRJ): Extended;
  85. class operator Implicit(Value: boolean): TRJ;
  86. class operator Implicit(const [ref] Value: TRJ): boolean;
  87. class operator Implicit(const Value: TJValue): TRJ;
  88. class operator Implicit(const [ref] Value: TRJ): TJValue;
  89. function ToStr(const ADefault: string = ''): string;
  90. function ToInt(ADefault: Integer = 0): Integer;
  91. function ToInt64(ADefault: Int64 = 0): Int64;
  92. function ToFloat(ADefault: Extended = 0.0): Extended;
  93. function ToBool(ADefault: boolean = False): boolean;
  94. property Items[const APath: TRPath]: TRJ read GetItems write SetItems; default;
  95. property S[const APath: TRPath]: string read GetS write SetS;
  96. property I[const APath: TRPath]: Integer read GetI write SetI;
  97. property I64[const APath: TRPath]: Int64 read GetI64 write SetI64;
  98. property F[const APath: TRPath]: Extended read GetF write SetF;
  99. property B[const APath: TRPath]: boolean read GetB write SetB;
  100. property Pairs[AIndex: Integer]: TRJ read GetPairs;
  101. property Count: Integer read GetCount;
  102. property Index: Integer read GetIndex;
  103. property Key: string read GetKey;
  104. property RootRefCount: Integer read GetRootRefCount;
  105. property Root: TRJ read GetRoot;
  106. property Path: string read FPath;
  107. property JValue: TJValue read GeTJValue;
  108. function CloneJValue: TJValue;
  109. function IsRoot: boolean; inline;
  110. function RootIsJObject: boolean; inline;
  111. function RootIsJArray: boolean; inline;
  112. function IsJObject: boolean;
  113. function IsJArray: boolean;
  114. function IsJString: boolean;
  115. function IsJNumber: boolean;
  116. function IsJBool: boolean;
  117. function IsJNull: boolean;
  118. function IsNil: boolean;
  119. procedure Reset;
  120. function ToString: string;
  121. function ToJSON(AEncodeBelow32: boolean = true; AEncodeAbove127: boolean = true): string;
  122. function Format(AIndentation: Integer = 4): string;
  123. procedure ParseJValue(const AData: string; AUseBool: boolean = False; ARaiseExc: boolean = False);
  124. procedure LoadFromFile(const AFileName: string; AUseBool: boolean = False; ARaiseExc: boolean = False);
  125. procedure SaveToFile(const AFileName: string; AIndentation: Integer; AWriteBOM: boolean = False); overload;
  126. procedure SaveToFile(const AFileName: string; AEncodeBelow32: boolean = true; AEncodeAbove127: boolean = true; AWriteBOM: boolean = False); overload;
  127. end;
  128. { Iterators }
  129. TRJEnumerator = class
  130. private
  131. FPData: ^TRJ;
  132. FIndex: Integer;
  133. function GetCurrent: TRJ;
  134. public
  135. constructor Create(const [ref] AData: TRJ);
  136. function MoveNext: boolean;
  137. property Current: TRJ read GetCurrent;
  138. end;
  139. implementation
  140. { ============================================================================ }
  141. { TRJRoot }
  142. constructor TRJRoot.Create;
  143. begin
  144. inherited;
  145. FData := nil;
  146. end;
  147. destructor TRJRoot.Destroy;
  148. begin
  149. FData.Free;
  150. inherited;
  151. end;
  152. function TRJRoot.GetData: TJValue;
  153. begin
  154. Result := FData;
  155. end;
  156. procedure TRJRoot.SetData(const AValue: TJValue);
  157. begin
  158. FData := AValue;
  159. end;
  160. function TRJRoot.ForceData(AType: TJVType): TJValue;
  161. begin
  162. if not(FData is AType) then
  163. begin
  164. FData.Free;
  165. FData := AType.Create;
  166. end;
  167. Result := FData;
  168. end;
  169. { TRJRoot }
  170. { ============================================================================ }
  171. { TJValueHelper }
  172. type
  173. TJValueHelper = class helper for TJValue
  174. private
  175. procedure ObjSetItem(const AName: string; const AValue: TJValue);
  176. procedure ArrFill<T: TJValue>(ACount: Integer);
  177. procedure ArrInsert(const AIndex: Integer; const AValue: TJValue);
  178. procedure ArrSetItem(AIndex: Integer; const AValue: TJValue);
  179. function ToType<T>(ADefault: T): T;
  180. function GetOrCreate<T: TJValue>(AName: string): T;
  181. procedure SetValue(const APath: string; const AValue: TJValue);
  182. procedure TrySetValue(const APath: string; const AValue: TJValue);
  183. end;
  184. procedure TJValueHelper.ObjSetItem(const AName: string; const AValue: TJValue);
  185. var
  186. pairTmp: TJSONPair;
  187. begin
  188. pairTmp := TJObject(self).Get(AName);
  189. if pairTmp = nil then
  190. TJObject(self).AddPair(AName, AValue)
  191. else
  192. pairTmp.JSONValue := AValue;
  193. end;
  194. procedure TJValueHelper.ArrFill<T>(ACount: Integer);
  195. begin
  196. for var j := TJArray(self).Count to ACount do
  197. TJArray(self).AddElement(T.Create);
  198. end;
  199. procedure TJValueHelper.ArrInsert(const AIndex: Integer; const AValue: TJValue);
  200. begin
  201. TJArray(self).AddElement(AValue);
  202. for var I := AIndex to TJArray(self).Count - 2 do
  203. TJArray(self).AddElement(TJArray(self).Remove(AIndex));
  204. end;
  205. procedure TJValueHelper.ArrSetItem(AIndex: Integer; const AValue: TJValue);
  206. begin
  207. ArrFill<TJNull>(AIndex - 1);
  208. if AIndex <= TJArray(self).Count - 1 then
  209. TJArray(self).Remove(AIndex).Free;
  210. ArrInsert(AIndex, AValue);
  211. end;
  212. procedure TJValueHelper.SetValue(const APath: string; const AValue: TJValue);
  213. var
  214. LParser: TJSONPathParser;
  215. preName: string;
  216. jv: TJValue;
  217. begin
  218. if APath.IsEmpty then
  219. raise Exception.Create('TJValueHelper.SetValue: path cannot be empty');
  220. jv := self;
  221. LParser := TJSONPathParser.Create(APath);
  222. LParser.NextToken;
  223. while true do
  224. begin
  225. preName := LParser.TokenName;
  226. LParser.NextToken;
  227. case LParser.Token of
  228. TJSONPathParser.TToken.Name:
  229. jv := jv.GetOrCreate<TJObject>(preName);
  230. TJSONPathParser.TToken.ArrayIndex:
  231. jv := jv.GetOrCreate<TJArray>(preName);
  232. TJSONPathParser.TToken.Eof:
  233. begin
  234. if jv is TJObject then
  235. jv.ObjSetItem(preName, AValue)
  236. else
  237. jv.ArrSetItem(preName.ToInteger, AValue);
  238. break;
  239. end;
  240. else
  241. raise Exception.Create('TJValueHelper.SetValue, LParser.Token Error!');
  242. end;
  243. end;
  244. end;
  245. procedure TJValueHelper.TrySetValue(const APath: string; const AValue: TJValue);
  246. begin
  247. try
  248. SetValue(APath, AValue);
  249. except
  250. on E: Exception do
  251. begin
  252. AValue.Free;
  253. raise Exception.Create(E.Message);
  254. end;
  255. end;
  256. end;
  257. function TJValueHelper.ToType<T>(ADefault: T): T;
  258. begin
  259. if self = nil then
  260. Exit(ADefault);
  261. try
  262. Result := AsType<T>;
  263. except
  264. Result := ADefault;
  265. end;
  266. end;
  267. function TJValueHelper.GetOrCreate<T>(AName: string): T;
  268. begin
  269. if self is TJObject then
  270. begin
  271. Result := T(TJObject(self).GetValue(AName));
  272. if not(Result is T) then
  273. begin
  274. Result := T.Create;
  275. ObjSetItem(AName, Result);
  276. end;
  277. end
  278. else if self is TJArray then
  279. begin
  280. ArrFill<TJNull>(AName.ToInteger);
  281. Result := T(TJArray(self).Items[AName.ToInteger]);
  282. if not(Result is T) then
  283. begin
  284. Result := T.Create;
  285. ArrSetItem(AName.ToInteger, Result);
  286. end;
  287. end
  288. else
  289. begin
  290. raise Exception.Create('GetOrCreate<T> Error, self must be TJO or TJA');
  291. end;
  292. end;
  293. { TJValueHelper }
  294. { ============================================================================ }
  295. { TRPath }
  296. class operator TRPath.Implicit(const Value: string): TRPath;
  297. begin
  298. Result.FData := Value;
  299. end;
  300. class operator TRPath.Implicit(Value: Integer): TRPath;
  301. begin
  302. Result.FData := '[' + Value.ToString + ']';
  303. end;
  304. class operator TRPath.Implicit(const [ref] Value: TRPath): string;
  305. begin
  306. Result := Value.FData;
  307. end;
  308. { TRPath }
  309. { ============================================================================ }
  310. { TRJEnumerator }
  311. constructor TRJEnumerator.Create(const [ref] AData: TRJ);
  312. begin
  313. inherited Create;
  314. FPData := @AData;
  315. FIndex := -1;
  316. end;
  317. function TRJEnumerator.GetCurrent: TRJ;
  318. var
  319. jvTmp: TJValue;
  320. begin
  321. Result.Reset;
  322. Result.FIRoot := FPData^.FIRoot;
  323. jvTmp := FPData^.GeTJValue;
  324. if jvTmp is TJObject then
  325. begin
  326. if FPData^.FPath = '' then
  327. Result.FPath := TJObject(jvTmp).Pairs[FIndex].JsonString.Value
  328. else
  329. Result.FPath := FPData^.FPath + '.' + TJObject(jvTmp).Pairs[FIndex].JsonString.Value;
  330. end
  331. else if jvTmp is TJArray then
  332. begin
  333. Result.FPath := FPData^.FPath + '[' + FIndex.ToString + ']';
  334. end;
  335. end;
  336. function TRJEnumerator.MoveNext: boolean;
  337. begin
  338. Inc(FIndex);
  339. Exit(FIndex < FPData^.Count)
  340. end;
  341. { TRJEnumerator }
  342. { ============================================================================ }
  343. { TRJ }
  344. function TRJ.GetEnumerator(): TRJEnumerator;
  345. begin
  346. Result := TRJEnumerator.Create(self);
  347. end;
  348. class operator TRJ.Initialize(out Dest: TRJ);
  349. begin
  350. Dest.FIRoot := TRJRoot.Create;
  351. Dest.FPath := '';
  352. end;
  353. class operator TRJ.Finalize(var Dest: TRJ);
  354. begin
  355. Dest.FIRoot := nil;
  356. end;
  357. function TRJ.GetRootRefCount: Integer;
  358. begin
  359. Result := (FIRoot as TRJRoot).RefCount;
  360. end;
  361. function TRJ.ForceRootJValue(const APath: string): TJValue;
  362. begin
  363. if APath.StartsWith('[') then
  364. Result := FIRoot.ForceData(TJArray)
  365. else
  366. Result := FIRoot.ForceData(TJObject);
  367. end;
  368. function TRJ.LinkPath(const ALeft, ARight: string): string;
  369. begin
  370. if ALeft.IsEmpty then
  371. Result := ARight
  372. else if ARight.IsEmpty then
  373. Result := ALeft
  374. else if ARight.StartsWith('[') then
  375. Result := ALeft + ARight
  376. else
  377. Result := ALeft + '.' + ARight;
  378. end;
  379. function TRJ.GeTJValue: TJValue;
  380. begin
  381. Result := FIRoot.Data.FindValue(FPath);
  382. end;
  383. function TRJ.CloneJValue: TJValue;
  384. begin
  385. Result := GeTJValue;
  386. if Result <> nil then
  387. Result := Result.Clone as TJValue
  388. else
  389. Result := TJNull.Create;
  390. end;
  391. class operator TRJ.Assign(var Dest: TRJ; const [ref] Src: TRJ);
  392. begin
  393. if Dest.FPath.IsEmpty then
  394. begin
  395. Dest.FIRoot := Src.FIRoot;
  396. Dest.FPath := Src.FPath;
  397. end
  398. else
  399. begin
  400. Dest.SetValue(Src);
  401. end;
  402. end;
  403. class operator TRJ.Implicit(const Value: string): TRJ;
  404. begin
  405. Result.FIRoot.Data := TJString.Create(Value);
  406. end;
  407. class operator TRJ.Implicit(const [ref] Value: TRJ): string;
  408. begin
  409. Result := Value.ToStr('');
  410. end;
  411. class operator TRJ.Implicit(Value: Integer): TRJ;
  412. begin
  413. Result.FIRoot.Data := TJNumber.Create(Value);
  414. end;
  415. class operator TRJ.Implicit(const [ref] Value: TRJ): Integer;
  416. begin
  417. Result := Value.ToInt(0);
  418. end;
  419. class operator TRJ.Implicit(Value: Int64): TRJ;
  420. begin
  421. Result.FIRoot.Data := TJNumber.Create(Value);
  422. end;
  423. class operator TRJ.Implicit(const [ref] Value: TRJ): Int64;
  424. begin
  425. Result := Value.ToInt64(0);
  426. end;
  427. class operator TRJ.Implicit(Value: Extended): TRJ;
  428. begin
  429. Result.FIRoot.Data := TJNumber.Create(Value);
  430. end;
  431. class operator TRJ.Implicit(const [ref] Value: TRJ): Extended;
  432. begin
  433. Result := Value.ToFloat(0.0);
  434. end;
  435. class operator TRJ.Implicit(Value: boolean): TRJ;
  436. begin
  437. Result.FIRoot.Data := TJBool.Create(Value);
  438. end;
  439. class operator TRJ.Implicit(const [ref] Value: TRJ): boolean;
  440. begin
  441. Result := Value.ToBool(False);
  442. end;
  443. class operator TRJ.Implicit(const Value: TJValue): TRJ;
  444. begin
  445. Result.FIRoot.Data := Value;
  446. end;
  447. class operator TRJ.Implicit(const [ref] Value: TRJ): TJValue;
  448. begin
  449. Result := Value.GeTJValue;
  450. end;
  451. function TRJ.ToStr(const ADefault: string): string;
  452. begin
  453. Result := FIRoot.Data.FindValue(FPath).ToType<string>(ADefault);
  454. end;
  455. function TRJ.ToInt(ADefault: Integer = 0): Integer;
  456. begin
  457. Result := FIRoot.Data.FindValue(FPath).ToType<Integer>(ADefault);
  458. end;
  459. function TRJ.ToInt64(ADefault: Int64 = 0): Int64;
  460. begin
  461. Result := FIRoot.Data.FindValue(FPath).ToType<Int64>(ADefault);
  462. end;
  463. function TRJ.ToFloat(ADefault: Extended = 0.0): Extended;
  464. begin
  465. Result := FIRoot.Data.FindValue(FPath).ToType<Extended>(ADefault);
  466. end;
  467. function TRJ.ToBool(ADefault: boolean = False): boolean;
  468. begin
  469. Result := FIRoot.Data.FindValue(FPath).ToType<boolean>(ADefault);
  470. end;
  471. function TRJ.GetItems(const APath: TRPath): TRJ;
  472. begin
  473. Result.FIRoot := FIRoot;
  474. Result.FPath := LinkPath(FPath, APath);
  475. end;
  476. function TRJ.GetPairs(AIndex: Integer): TRJ;
  477. var
  478. jvTmp: TJValue;
  479. begin
  480. jvTmp := GeTJValue;
  481. if (jvTmp is TJObject) then
  482. Result := GetItems(TJObject(jvTmp).Pairs[AIndex].JsonString.Value);
  483. end;
  484. procedure TRJ.SetValue(const [ref] AValue: TRJ);
  485. var
  486. LValue: TJValue;
  487. begin
  488. {$IFDEF DEBUG}
  489. if FPath.IsEmpty then
  490. raise Exception.Create(' TRJ.SetValue: Path is empty');
  491. {$ENDIF}
  492. LValue := AValue.CloneJValue;
  493. try
  494. ForceRootJValue(FPath).SetValue(FPath, LValue);
  495. except
  496. on E: Exception do
  497. begin
  498. LValue.Free;
  499. raise Exception.Create(E.Message);
  500. end;
  501. end;
  502. end;
  503. procedure TRJ.SetItems(const APath: TRPath; const [ref] AValue: TRJ);
  504. var
  505. tmp: TRJ;
  506. begin
  507. tmp.FIRoot := FIRoot;
  508. tmp.FPath := LinkPath(FPath, APath);
  509. tmp.SetValue(AValue)
  510. end;
  511. function TRJ.GetS(const APath: TRPath): string;
  512. var
  513. LPath: string;
  514. begin
  515. LPath := LinkPath(FPath, APath);
  516. Result := ForceRootJValue(LPath).FindValue(LPath).ToType<string>('');
  517. end;
  518. procedure TRJ.SetS(const APath: TRPath; AValue: string);
  519. var
  520. LPath: string;
  521. begin
  522. LPath := LinkPath(FPath, APath);
  523. ForceRootJValue(LPath).TrySetValue(LPath, TJString.Create(AValue));
  524. end;
  525. function TRJ.GetI(const APath: TRPath): Integer;
  526. var
  527. LPath: string;
  528. begin
  529. LPath := LinkPath(FPath, APath);
  530. Result := ForceRootJValue(LPath).FindValue(LPath).ToType<Integer>(0);
  531. end;
  532. procedure TRJ.SetI(const APath: TRPath; AValue: Integer);
  533. var
  534. LPath: string;
  535. begin
  536. LPath := LinkPath(FPath, APath);
  537. ForceRootJValue(LPath).TrySetValue(LPath, TJNumber.Create(AValue));
  538. end;
  539. function TRJ.GetI64(const APath: TRPath): Int64;
  540. var
  541. LPath: string;
  542. begin
  543. LPath := LinkPath(FPath, APath);
  544. Result := ForceRootJValue(LPath).FindValue(LPath).ToType<Int64>(0);
  545. end;
  546. procedure TRJ.SetI64(const APath: TRPath; AValue: Int64);
  547. var
  548. LPath: string;
  549. begin
  550. LPath := LinkPath(FPath, APath);
  551. ForceRootJValue(LPath).TrySetValue(LPath, TJNumber.Create(AValue));
  552. end;
  553. function TRJ.GetF(const APath: TRPath): Extended;
  554. var
  555. LPath: string;
  556. begin
  557. LPath := LinkPath(FPath, APath);
  558. Result := ForceRootJValue(LPath).FindValue(LPath).ToType<Extended>(0.0);
  559. end;
  560. procedure TRJ.SetF(const APath: TRPath; AValue: Extended);
  561. var
  562. LPath: string;
  563. begin
  564. LPath := LinkPath(FPath, APath);
  565. ForceRootJValue(LPath).TrySetValue(LPath, TJNumber.Create(AValue));
  566. end;
  567. function TRJ.GetB(const APath: TRPath): boolean;
  568. var
  569. LPath: string;
  570. begin
  571. LPath := LinkPath(FPath, APath);
  572. Result := ForceRootJValue(LPath).FindValue(LPath).ToType<boolean>(False);
  573. end;
  574. procedure TRJ.SetB(const APath: TRPath; AValue: boolean);
  575. var
  576. LPath: string;
  577. begin
  578. LPath := LinkPath(FPath, APath);
  579. ForceRootJValue(LPath).TrySetValue(LPath, TJBool.Create(AValue));
  580. end;
  581. function TRJ.GetCount: Integer;
  582. var
  583. jvTemp: TJValue;
  584. begin
  585. jvTemp := GeTJValue;
  586. if jvTemp is TJArray then
  587. Result := TJArray(jvTemp).Count
  588. else if jvTemp is TJObject then
  589. Result := TJObject(jvTemp).Count
  590. else
  591. Result := 0;
  592. end;
  593. function TRJ.GetIndex: Integer;
  594. var
  595. strTmp: string;
  596. begin
  597. Result := -1;
  598. strTmp := FPath.Substring(FPath.LastIndexOf('[') + 1);
  599. if strTmp.EndsWith(']') then
  600. Result := StrToIntDef(strTmp.TrimRight([']']), -1);
  601. end;
  602. function TRJ.GetKey: string;
  603. begin
  604. Result := FPath.Substring(FPath.LastIndexOf('.') + 1);
  605. if Result.EndsWith(']') then
  606. Result := '';
  607. end;
  608. function TRJ.GetRoot: TRJ;
  609. begin
  610. Result.FIRoot := FIRoot;
  611. // Result.FPath := '';
  612. end;
  613. function TRJ.IsRoot: boolean;
  614. begin
  615. Result := FPath.IsEmpty;
  616. end;
  617. function TRJ.RootIsJObject: boolean;
  618. begin
  619. Result := FIRoot.Data is TJObject;
  620. end;
  621. function TRJ.RootIsJArray: boolean;
  622. begin
  623. Result := FIRoot.Data is TJArray;
  624. end;
  625. function TRJ.IsJObject: boolean;
  626. begin
  627. Result := GeTJValue is TJObject;
  628. end;
  629. function TRJ.IsJArray: boolean;
  630. begin
  631. Result := GeTJValue is TJArray;
  632. end;
  633. function TRJ.IsJString: boolean;
  634. begin
  635. Result := GeTJValue is TJString;
  636. end;
  637. function TRJ.IsJNumber: boolean;
  638. begin
  639. Result := GeTJValue is TJNumber;
  640. end;
  641. function TRJ.IsJBool: boolean;
  642. begin
  643. Result := GeTJValue is TJBool;
  644. end;
  645. function TRJ.IsJNull: boolean;
  646. begin
  647. Result := GeTJValue is TJNull;
  648. end;
  649. function TRJ.IsNil: boolean;
  650. begin
  651. Result := GeTJValue = nil;
  652. end;
  653. procedure TRJ.Reset;
  654. begin
  655. FIRoot := TRJRoot.Create;
  656. FPath := '';
  657. end;
  658. function TRJ.ToJSON(AEncodeBelow32: boolean = true; AEncodeAbove127: boolean = true): string;
  659. var
  660. LValue: TJValue;
  661. Options: TJSONAncestor.TJSONOutputOptions;
  662. begin
  663. Result := '';
  664. LValue := GeTJValue;
  665. if LValue <> nil then
  666. begin
  667. Options := [];
  668. if AEncodeBelow32 then
  669. Include(Options, TJSONAncestor.TJSONOutputOption.EncodeBelow32);
  670. if AEncodeAbove127 then
  671. Include(Options, TJSONAncestor.TJSONOutputOption.EncodeAbove127);
  672. Result := LValue.ToJSON(Options);
  673. end;
  674. end;
  675. function TRJ.ToString: string;
  676. begin
  677. Result := ToJSON(False, False);
  678. end;
  679. function TRJ.Format(AIndentation: Integer): string;
  680. var
  681. LValue: TJValue;
  682. begin
  683. Result := '';
  684. LValue := GeTJValue;
  685. if LValue <> nil then
  686. Result := LValue.Format(AIndentation)
  687. end;
  688. procedure TRJ.ParseJValue(const AData: string; AUseBool: boolean; ARaiseExc: boolean);
  689. begin
  690. Reset;
  691. FIRoot.Data := TJValue.ParseJSONValue(AData, AUseBool, ARaiseExc);
  692. end;
  693. procedure TRJ.LoadFromFile(const AFileName: string; AUseBool: boolean; ARaiseExc: boolean);
  694. begin
  695. ParseJValue(TFile.ReadAllText(AFileName, TEncoding.UTF8), AUseBool, ARaiseExc);
  696. end;
  697. procedure TRJ.SaveToFile(const AFileName: string; AIndentation: Integer; AWriteBOM: boolean);
  698. var
  699. strs: TStrings;
  700. begin
  701. strs := TStringList.Create;
  702. try
  703. strs.WriteBOM := AWriteBOM;
  704. strs.Text := Format(AIndentation);
  705. strs.SaveToFile(AFileName, TEncoding.UTF8);
  706. finally
  707. strs.Free;
  708. end;
  709. end;
  710. procedure TRJ.SaveToFile(const AFileName: string; AEncodeBelow32: boolean = true; AEncodeAbove127: boolean = true; AWriteBOM: boolean = False);
  711. var
  712. strs: TStrings;
  713. begin
  714. strs := TStringList.Create;
  715. try
  716. strs.WriteBOM := AWriteBOM;
  717. strs.Text := ToJSON(AEncodeBelow32, AEncodeAbove127);
  718. strs.SaveToFile(AFileName, TEncoding.UTF8);
  719. finally
  720. strs.Free;
  721. end;
  722. end;
  723. { TRJ }
  724. { ============================================================================ }
  725. end.