jsonhelper.pas 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. unit jsonhelper;
  2. interface
  3. uses
  4. System.Generics.Collections, System.JSON, System.IOUtils, System.SysUtils;
  5. type
  6. TJSONKind = (jkNone, jkObject, jkArray, jkString, jkNumber, jkBoolean, jkNull);
  7. TJSONPairHelper = class helper for TJSONPair
  8. public
  9. procedure Rename(ANewName: string);
  10. end;
  11. TJSONValueHelper = class helper for TJSONValue
  12. private
  13. function GetJsonKind: TJSONKind;
  14. function GetItemCount: Integer;
  15. function GetItem(const AIndex: Integer): TJSONAncestor;
  16. public
  17. property JsonKind: TJSONKind read GetJsonKind;
  18. property ItemCount: Integer read GetItemCount;
  19. property Items[const AIndex: Integer]: TJSONAncestor read GetItem; Default;
  20. public
  21. function IsObjectOrArray: boolean;
  22. class function LoadFromFile(const AFileName: string; AUseBool: boolean = False; ARaiseExc: boolean = False): TJSONValue;
  23. end;
  24. TJSONObjectHelper = class helper for TJSONObject
  25. public
  26. function DeletePair(AIndex: Integer): TJSONPair; overload;
  27. function DeletePair(const AItem: TJSONPair): TJSONPair; overload;
  28. procedure InsertPair(AIndex: NativeInt; const AValue: TJSONPair);
  29. procedure Move(ACurIndex, ANewIndex: NativeInt);
  30. end;
  31. TJSONArrayHelper = class helper for TJSONArray
  32. public
  33. function Delete(const AItem: TJSONValue): TJSONValue;
  34. function IndexOf(const AItem: TJSONValue): Integer;
  35. procedure SetValue(const AIndex: Integer; const AValue: TJSONValue);
  36. procedure InsertElement(AIndex: NativeInt; const AValue: TJSONValue);
  37. procedure Move(ACurIndex, ANewIndex: NativeInt);
  38. end;
  39. function JSONFormat(AValue: TJSONValue; AIndentation: Integer; AEncodeBelow32: boolean; AEncodeAbove127: boolean): string;
  40. implementation
  41. function JSONToUniCode(const AStr: string; AEncodeBelow32: boolean = True; AEncodeAbove127: boolean = True): string;
  42. var
  43. ch: char;
  44. I: Integer;
  45. UnicodeValue: Integer;
  46. Buff: array [0 .. 5] of char;
  47. begin
  48. for I := 1 to AStr.Length do
  49. begin
  50. ch := AStr[I];
  51. case ch of
  52. #0 .. #7, #$b, #$e .. #31, #$0080 .. High(char):
  53. begin
  54. UnicodeValue := Ord(ch);
  55. if AEncodeBelow32 and (UnicodeValue < 32) or AEncodeAbove127 and (UnicodeValue > 127) then
  56. begin
  57. Buff[0] := '\';
  58. Buff[1] := 'u';
  59. Buff[2] := char(DecimalToHex((UnicodeValue and 61440) shr 12));
  60. Buff[3] := char(DecimalToHex((UnicodeValue and 3840) shr 8));
  61. Buff[4] := char(DecimalToHex((UnicodeValue and 240) shr 4));
  62. Buff[5] := char(DecimalToHex((UnicodeValue and 15)));
  63. Result := Result + Buff;
  64. end
  65. else
  66. begin
  67. Result := Result + ch;
  68. end;
  69. end
  70. else
  71. begin
  72. Result := Result + ch;
  73. end;
  74. end;
  75. end;
  76. end;
  77. function JsonToJsonStr(AValue: TJSONValue; AEncodeBelow32: boolean = True; AEncodeAbove127: boolean = True): string;
  78. var
  79. Options: TJSONAncestor.TJSONOutputOptions;
  80. begin
  81. Result := '';
  82. if AValue <> nil then
  83. begin
  84. Options := [];
  85. if AEncodeBelow32 then
  86. Include(Options, TJSONAncestor.TJSONOutputOption.EncodeBelow32);
  87. if AEncodeAbove127 then
  88. Include(Options, TJSONAncestor.TJSONOutputOption.EncodeAbove127);
  89. Result := AValue.ToJSON(Options);
  90. end;
  91. end;
  92. function JSONFormat(AValue: TJSONValue; AIndentation: Integer; AEncodeBelow32: boolean; AEncodeAbove127: boolean): string;
  93. begin
  94. if AIndentation >= 0 then
  95. begin
  96. Result := '';
  97. if AValue <> nil then
  98. begin
  99. Result := AValue.Format(AIndentation);
  100. if AEncodeBelow32 or AEncodeAbove127 then
  101. begin
  102. Result := JSONToUniCode(Result, AEncodeBelow32, AEncodeAbove127);
  103. end;
  104. end;
  105. end
  106. else
  107. begin
  108. Result := JsonToJsonStr(AValue, AEncodeBelow32, AEncodeAbove127);
  109. end;
  110. end;
  111. procedure TJSONPairHelper.Rename(ANewName: string);
  112. begin
  113. SetJsonString(TJSONString.Create(ANewName));
  114. end;
  115. ////////////////////////////////////////////////////////////////////////////////
  116. // TJSONValue
  117. function TJSONValueHelper.GetJsonKind: TJSONKind;
  118. begin
  119. if self = nil then
  120. Exit(jkNone);
  121. if ClassType = TJSONObject then
  122. begin
  123. Result := jkObject;
  124. end
  125. else if ClassType = TJSONArray then
  126. begin
  127. Result := jkArray;
  128. end
  129. else if ClassType = TJSONString then
  130. begin
  131. Result := jkString;
  132. end
  133. else if ClassType = TJSONNumber then
  134. begin
  135. Result := jkNumber;
  136. end
  137. else if ClassType = TJSONBool then
  138. begin
  139. Result := jkBoolean;
  140. end
  141. else if ClassType = TJSONNull then
  142. begin
  143. Result := jkNull;
  144. end
  145. else
  146. begin
  147. Result := jkNone;
  148. end;
  149. end;
  150. function TJSONValueHelper.IsObjectOrArray: boolean;
  151. begin
  152. Result := (self is TJSONObject) or (self is TJSONArray);
  153. end;
  154. class function TJSONValueHelper.LoadFromFile(const AFileName: string; AUseBool: boolean; ARaiseExc: boolean): TJSONValue;
  155. begin
  156. Result := nil;
  157. try
  158. Result := TJSONValue.ParseJSONValue(TFile.ReadAllText(AFileName, TEncoding.UTF8), AUseBool, ARaiseExc);
  159. except
  160. on E: Exception do
  161. begin
  162. if ARaiseExc then
  163. begin
  164. raise Exception.Create(E.Message);
  165. end;
  166. end;
  167. end;
  168. end;
  169. function TJSONValueHelper.GetItemCount: Integer;
  170. begin
  171. if self is TJSONObject then
  172. Result := TJSONObject(self).Count
  173. else if self is TJSONArray then
  174. Result := TJSONArray(self).Count
  175. else
  176. Result := 0;
  177. end;
  178. function TJSONValueHelper.GetItem(const AIndex: Integer): TJSONAncestor;
  179. begin
  180. if self is TJSONObject then
  181. Result := TJSONObject(self).Pairs[AIndex]
  182. else if self is TJSONArray then
  183. Result := TJSONArray(self)[AIndex]
  184. else
  185. Result := nil;
  186. end;
  187. ////////////////////////////////////////////////////////////////////////////////
  188. // TJSONObject
  189. function TJSONObjectHelper.DeletePair(AIndex: Integer): TJSONPair;
  190. begin
  191. with self do
  192. begin
  193. if (AIndex >= 0) and (AIndex < FMembers.Count) then
  194. begin
  195. Result := FMembers[AIndex];
  196. FMembers.Remove(Result);
  197. end
  198. else
  199. begin
  200. Result := nil;
  201. end;
  202. end;
  203. end;
  204. function TJSONObjectHelper.DeletePair(const AItem: TJSONPair): TJSONPair;
  205. begin
  206. with self do
  207. begin
  208. Exit(FMembers.Extract(AItem));
  209. end;
  210. end;
  211. procedure TJSONObjectHelper.InsertPair(AIndex: NativeInt; const AValue: TJSONPair);
  212. begin
  213. with self do
  214. begin
  215. FMembers.Insert(AIndex, AValue);
  216. end;
  217. end;
  218. procedure TJSONObjectHelper.Move(ACurIndex, ANewIndex: NativeInt);
  219. begin
  220. with self do
  221. begin
  222. FMembers.Move(ACurIndex, ANewIndex);
  223. end;
  224. end;
  225. function TJSONArrayHelper.Delete(const AItem: TJSONValue): TJSONValue;
  226. begin
  227. with self do
  228. begin
  229. Result := FElements.Extract(AItem);
  230. end;
  231. end;
  232. function TJSONArrayHelper.IndexOf(const AItem: TJSONValue): Integer;
  233. begin
  234. with self do
  235. begin
  236. Result := FElements.IndexOf(AItem);
  237. end;
  238. end;
  239. procedure TJSONArrayHelper.SetValue(const AIndex: Integer; const AValue: TJSONValue);
  240. begin
  241. with self do
  242. begin
  243. if FElements[AIndex].Owned then
  244. FElements[AIndex].Free;
  245. FElements[AIndex] := AValue;
  246. end;
  247. end;
  248. procedure TJSONArrayHelper.InsertElement(AIndex: NativeInt; const AValue: TJSONValue);
  249. begin
  250. with self do
  251. begin
  252. FElements.Insert(AIndex, AValue);
  253. end;
  254. end;
  255. procedure TJSONArrayHelper.Move(ACurIndex, ANewIndex: NativeInt);
  256. begin
  257. with self do
  258. begin
  259. FElements.Move(ACurIndex, ANewIndex);
  260. end;
  261. end;
  262. end.