Quick.Json.Serializer.pas 57 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800
  1. { ***************************************************************************
  2. Copyright (c) 2015-2020 Kike Pérez
  3. Unit : Quick.JSON.Serializer
  4. Description : Json Serializer
  5. Author : Kike Pérez
  6. Version : 1.11
  7. Created : 21/05/2018
  8. Modified : 22/03/2020
  9. This file is part of QuickLib: https://github.com/exilon/QuickLib
  10. ***************************************************************************
  11. Licensed under the Apache License, Version 2.0 (the "License");
  12. you may not use this file except in compliance with the License.
  13. You may obtain a copy of the License at
  14. http://www.apache.org/licenses/LICENSE-2.0
  15. Unless required by applicable law or agreed to in writing, software
  16. distributed under the License is distributed on an "AS IS" BASIS,
  17. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  18. See the License for the specific language governing permissions and
  19. limitations under the License.
  20. *************************************************************************** }
  21. unit Quick.Json.Serializer;
  22. {$i QuickLib.inc}
  23. interface
  24. uses
  25. Classes,
  26. SysUtils,
  27. Rtti,
  28. TypInfo,
  29. {$IFDEF FPC}
  30. rttiutils,
  31. fpjson,
  32. jsonparser,
  33. strUtils,
  34. //jsonreader,
  35. //fpjsonrtti,
  36. Quick.Json.fpc.Compatibility,
  37. {$ELSE}
  38. {$IFDEF DELPHIXE7_UP}
  39. System.Json,
  40. {$ENDIF}
  41. {$IFDEF DELPHIRX10_UP}
  42. {$ENDIF}
  43. Variants,
  44. {$ENDIF}
  45. DateUtils,
  46. Quick.Commons,
  47. Quick.JSON.Utils;
  48. type
  49. EJsonSerializeError = class(Exception);
  50. EJsonDeserializeError = class(Exception);
  51. {$IFNDEF FPC}
  52. TNotSerializableProperty = class(TCustomAttribute);
  53. TCommentProperty = class(TCustomAttribute)
  54. private
  55. fComment : string;
  56. public
  57. constructor Create(const aComment: string);
  58. property Comment : string read fComment;
  59. end;
  60. TCustomNameProperty = class(TCustomAttribute)
  61. private
  62. fName : string;
  63. public
  64. constructor Create(const aName: string);
  65. property Name : string read fName;
  66. end;
  67. {$ENDIF}
  68. IJsonSerializer = interface
  69. ['{CA26F7AE-F1FE-41BE-9C23-723A687F60D1}']
  70. function JsonToObject(aType: TClass; const aJson: string): TObject; overload;
  71. function JsonToObject(aObject: TObject; const aJson: string): TObject; overload;
  72. function ObjectToJson(aObject : TObject; aIndent : Boolean = False): string;
  73. function ValueToJson(aValue : TValue; aIndent : Boolean = False) : string;
  74. end;
  75. TSerializeLevel = (slPublicProperty, slPublishedProperty);
  76. TRTTIJson = class
  77. private
  78. fSerializeLevel : TSerializeLevel;
  79. fUseEnumNames : Boolean;
  80. fUseJsonCaseSense : Boolean;
  81. function GetValue(aAddr: Pointer; aType: TRTTIType): TValue; overload;
  82. function GetValue(aAddr: Pointer; aTypeInfo: PTypeInfo): TValue; overload;
  83. function IsAllowedProperty(aObject : TObject; const aPropertyName : string) : Boolean;
  84. function IsGenericList(aObject : TObject) : Boolean;
  85. function IsGenericXArray(const aClassName : string) : Boolean;
  86. function GetPropertyValue(Instance : TObject; const PropertyName : string) : TValue;
  87. function GetPropertyValueFromObject(Instance : TObject; const PropertyName : string) : TValue;
  88. {$IFNDEF FPC}
  89. function GetFieldValueFromRecord(aValue : TValue; const FieldName : string) : TValue;
  90. {$ENDIF}
  91. procedure SetPropertyValue(Instance : TObject; aPropInfo : PPropInfo; aValue : TValue); overload;
  92. procedure SetPropertyValue(Instance : TObject; const PropertyName : string; aValue : TValue); overload;
  93. {$IFDEF FPC}
  94. function FloatProperty(aObject : TObject; aPropInfo: PPropInfo): string;
  95. function GetPropType(aPropInfo: PPropInfo): PTypeInfo;
  96. procedure LoadSetProperty(aInstance : TObject; aPropInfo: PPropInfo; const aValue: string);
  97. {$ENDIF}
  98. public
  99. constructor Create(aSerializeLevel : TSerializeLevel; aUseEnumNames : Boolean = True);
  100. property UseEnumNames : Boolean read fUseEnumNames write fUseEnumNames;
  101. property UseJsonCaseSense : Boolean read fUseJsonCaseSense write fUseJsonCaseSense;
  102. {$IFNDEF FPC}
  103. function DeserializeDynArray(aTypeInfo : PTypeInfo; aObject : TObject; const aJsonArray: TJSONArray) : TValue;
  104. function DeserializeRecord(aRecord : TValue; aObject : TObject; const aJson : TJSONObject) : TValue;
  105. {$ELSE}
  106. procedure DeserializeDynArray(aTypeInfo: PTypeInfo; const aPropertyName : string; aObject: TObject; const aJsonArray: TJSONArray);
  107. {$ENDIF}
  108. function DeserializeClass(aType : TClass; const aJson : TJSONObject) : TObject;
  109. function DeserializeObject(aObject : TObject; const aJson : TJSONObject) : TObject; overload;
  110. {$IFNDEF FPC}
  111. function DeserializeList(aObject: TObject; const aName : string; const aJson: TJSONObject) : TObject;
  112. procedure DeserializeXArray(Instance : TObject; aRecord : TValue; aProperty : TRttiProperty; const aPropertyName : string; aJson : TJsonObject);
  113. {$ENDIF}
  114. function DeserializeProperty(aObject : TObject; const aName : string; aProperty : TRttiProperty; const aJson : TJSONObject) : TObject; overload;
  115. {$IFNDEF FPC}
  116. function DeserializeType(aObject : TObject; aType : TTypeKind; aTypeInfo : PTypeInfo; const aValue: string) : TValue;
  117. {$ELSE}
  118. function DeserializeType(aObject : TObject; aType : TTypeKind; const aPropertyName, aValue: string) : TValue;
  119. {$ENDIF}
  120. {$IFNDEF FPC}
  121. function Serialize(const aName : string; aValue : TValue) : TJSONPair; overload;
  122. {$ELSE}
  123. function Serialize(aObject : TObject; aType : TTypeKind; const aPropertyName : string) : TJSONPair;
  124. function Serialize(const aName : string; aValue : TValue) : TJSONPair;
  125. {$ENDIF}
  126. function Serialize(aObject : TObject) : TJSONObject; overload;
  127. function GetJsonPairValueByName(aJson : TJSONObject; const aName : string) : TJsonValue;
  128. function GetJsonPairByName(aJson : TJSONObject; const aName : string) : TJSONPair;
  129. end;
  130. TJsonSerializer = class(TInterfacedObject,IJsonSerializer)
  131. strict private
  132. fSerializeLevel : TSerializeLevel;
  133. fUseEnumNames : Boolean;
  134. fUseJsonCaseSense : Boolean;
  135. fRTTIJson : TRTTIJson;
  136. private
  137. procedure SetUseEnumNames(const Value: Boolean);
  138. procedure SetUseJsonCaseSense(const Value: Boolean);
  139. public
  140. constructor Create(aSerializeLevel: TSerializeLevel; aUseEnumNames : Boolean = True);
  141. destructor Destroy; override;
  142. property SerializeLevel : TSerializeLevel read fSerializeLevel;
  143. property UseEnumNames : Boolean read fUseEnumNames write SetUseEnumNames;
  144. property UseJsonCaseSense : Boolean read fUseJsonCaseSense write SetUseJsonCaseSense;
  145. function JsonToObject(aType : TClass; const aJson: string) : TObject; overload;
  146. function JsonToObject(aObject : TObject; const aJson: string) : TObject; overload;
  147. function ObjectToJson(aObject : TObject; aIndent : Boolean = False): string;
  148. function ObjectToJsonString(aObject : TObject; aIndent : Boolean = False): string;
  149. function ValueToJson(aValue : TValue; aIndent : Boolean = False) : string;
  150. function ValueToJsonString(aValue : TValue; aIndent : Boolean = False) : string;
  151. function ArrayToJson<T>(aArray : TArray<T>; aIndent : Boolean = False) : string;
  152. function ArrayToJsonString<T>(aArray : TArray<T>; aIndent : Boolean = False) : string;
  153. {$IFNDEF FPC}
  154. function JsonToArray<T>(const aJson : string) : TArray<T>;
  155. {$ENDIF}
  156. end;
  157. PPByte = ^PByte;
  158. resourcestring
  159. cNotSupportedDataType = 'Not supported "%s" data type "%s"';
  160. cNotSerializable = 'Object is not serializable';
  161. implementation
  162. uses
  163. System.Generics.Collections;
  164. { TRTTIJson }
  165. {$IFNDEF FPC}
  166. function TRTTIJson.DeserializeDynArray(aTypeInfo: PTypeInfo; aObject: TObject; const aJsonArray: TJSONArray) : TValue;
  167. var
  168. rType: PTypeInfo;
  169. len: NativeInt;
  170. pArr: Pointer;
  171. rItemValue: TValue;
  172. i: Integer;
  173. objClass: TClass;
  174. ctx : TRttiContext;
  175. json : TJSONObject;
  176. rDynArray : TRttiDynamicArrayType;
  177. propObj : TObject;
  178. begin
  179. if GetTypeData(aTypeInfo).DynArrElType = nil then Exit;
  180. if not assigned(aJsonArray) then Exit;
  181. len := aJsonArray.Count;
  182. rType := GetTypeData(aTypeInfo).DynArrElType^;
  183. pArr := nil;
  184. DynArraySetLength(pArr,aTypeInfo, 1, @len);
  185. try
  186. TValue.Make(@pArr,aTypeInfo, Result);
  187. rDynArray := ctx.GetType(Result.TypeInfo) as TRTTIDynamicArrayType;
  188. for i := 0 to aJsonArray.Count - 1 do
  189. begin
  190. rItemValue := nil;
  191. case rType.Kind of
  192. tkClass :
  193. begin
  194. if aJsonArray.Items[i] is TJSONObject then
  195. begin
  196. propObj := GetValue(PPByte(Result.GetReferenceToRawData)^ +rDynArray.ElementType.TypeSize * i, rDynArray.ElementType).AsObject;
  197. if propObj = nil then
  198. begin
  199. objClass := rType.TypeData.ClassType;
  200. rItemValue := DeserializeClass(objClass, TJSONObject(aJsonArray.Items[i]));
  201. end
  202. else
  203. begin
  204. DeserializeObject(propObj,TJSONObject(aJsonArray.Items[i]));
  205. end;
  206. end;
  207. end;
  208. tkRecord :
  209. begin
  210. json := TJSONObject(aJsonArray.Items[i]);
  211. rItemValue := DeserializeRecord(GetValue(PPByte(Result.GetReferenceToRawData)^ +rDynArray.ElementType.TypeSize * i,
  212. rDynArray.ElementType),aObject,json);
  213. end;
  214. tkMethod, tkPointer, tkClassRef ,tkInterface, tkProcedure :
  215. begin
  216. //skip these properties
  217. end
  218. else
  219. begin
  220. rItemValue := DeserializeType(aObject,rType.Kind,aTypeInfo,aJsonArray.Items[i].Value);
  221. end;
  222. end;
  223. if not rItemValue.IsEmpty then Result.SetArrayElement(i,rItemValue);
  224. end;
  225. //aProperty.SetValue(aObject,rValue);
  226. finally
  227. DynArrayClear(pArr,aTypeInfo);
  228. end;
  229. end;
  230. {$ELSE}
  231. procedure TRTTIJson.DeserializeDynArray(aTypeInfo: PTypeInfo; const aPropertyName : string; aObject: TObject; const aJsonArray: TJSONArray);
  232. var
  233. rType: PTypeInfo;
  234. len: NativeInt;
  235. pArr: Pointer;
  236. rItemValue: TValue;
  237. i: Integer;
  238. objClass: TClass;
  239. propObj : TObject;
  240. rValue : TValue;
  241. begin
  242. if GetTypeData(aTypeInfo).ElType2 = nil then Exit;
  243. len := aJsonArray.Count;
  244. rType := GetTypeData(aTypeInfo).ElType2;
  245. pArr := nil;
  246. DynArraySetLength(pArr,aTypeInfo, 1, @len);
  247. try
  248. TValue.Make(@pArr,aTypeInfo, rValue);
  249. for i := 0 to aJsonArray.Count - 1 do
  250. begin
  251. rItemValue := nil;
  252. case rType.Kind of
  253. tkClass :
  254. begin
  255. if aJsonArray.Items[i] is TJSONObject then
  256. begin
  257. propObj := GetValue(PPByte(rValue.GetReferenceToRawData)^ +GetTypeData(aTypeInfo).elSize * i, GetTypeData(aTypeInfo).ElType2).AsObject;
  258. if propObj = nil then
  259. begin
  260. objClass := GetTypeData(aTypeInfo).ClassType;
  261. rItemValue := DeserializeClass(objClass, TJSONObject(aJsonArray.Items[i]));
  262. end
  263. else
  264. begin
  265. DeserializeObject(propObj,TJSONObject(aJsonArray.Items[i]));
  266. end;
  267. end;
  268. end;
  269. tkRecord :
  270. begin
  271. {json := TJSONObject(aJsonArray.Items[i]);
  272. rItemValue := DeserializeRecord(GetValue(PPByte(Result.GetReferenceToRawData)^ +rDynArray.ElementType.TypeSize * i,
  273. rDynArray.ElementType),aObject,json); }
  274. end;
  275. tkMethod, tkPointer, tkClassRef ,tkInterface, tkProcedure :
  276. begin
  277. //skip these properties
  278. end
  279. else
  280. begin
  281. rItemValue := DeserializeType(aObject,GetTypeData(aTypeInfo).ElType2.Kind,aPropertyName,aJsonArray.Items[i].Value);
  282. end;
  283. end;
  284. if not rItemValue.IsEmpty then rValue.SetArrayElement(i,rItemValue);
  285. end;
  286. //aProperty.SetValue(aObject,rValue);
  287. SetDynArrayProp(aObject,GetPropInfo(aObject,aPropertyName),pArr);
  288. finally
  289. DynArrayClear(pArr,aTypeInfo);
  290. end;
  291. end;
  292. {$ENDIF}
  293. {$IFNDEF FPC}
  294. function TRTTIJson.DeserializeRecord(aRecord : TValue; aObject : TObject; const aJson : TJSONObject) : TValue;
  295. var
  296. ctx : TRttiContext;
  297. rRec : TRttiRecordType;
  298. rField : TRttiField;
  299. rValue : TValue;
  300. member : TJsonValue;
  301. jArray : TJSONArray;
  302. json : TJSONObject;
  303. objClass : TClass;
  304. propobj : TObject;
  305. begin
  306. rRec := ctx.GetType(aRecord.TypeInfo).AsRecord;
  307. for rField in rRec.GetFields do
  308. begin
  309. rValue := nil;
  310. //member := TJSONPair(aJson.GetValue(rField.Name));
  311. member := GetJsonPairValueByName(aJson,rField.Name);
  312. if member <> nil then
  313. case rField.FieldType.TypeKind of
  314. tkDynArray :
  315. begin
  316. jArray := TJSONObject.ParseJSONValue(member.ToJSON) as TJSONArray;
  317. try
  318. rValue := DeserializeDynArray(rField.FieldType.Handle,aObject,jArray);
  319. finally
  320. jArray.Free;
  321. end;
  322. end;
  323. tkClass :
  324. begin
  325. //if (member.JsonValue is TJSONObject) then
  326. begin
  327. propobj := rField.GetValue(@aRecord).AsObject;
  328. json := TJSONObject.ParseJSONValue(member.ToJson) as TJSONObject;
  329. try
  330. if propobj = nil then
  331. begin
  332. objClass := rField.FieldType.Handle^.TypeData.ClassType;// aProperty.PropertyType.Handle^.TypeData.ClassType;
  333. rValue := DeserializeClass(objClass,json);
  334. end
  335. else
  336. begin
  337. DeserializeObject(propobj,json);
  338. end;
  339. finally
  340. json.Free;
  341. end;
  342. end
  343. end;
  344. tkRecord :
  345. begin
  346. json := TJSONObject.ParseJSONValue(member.ToJson) as TJSONObject;
  347. try
  348. rValue := DeserializeRecord(rField.GetValue(aRecord.GetReferenceToRawData),aObject,json);
  349. finally
  350. json.Free;
  351. end;
  352. end
  353. else
  354. begin
  355. //rValue := DeserializeType(aObject,rField.FieldType.TypeKind,rField.FieldType.Handle,member.ToJson);
  356. //avoid return unicode escaped chars if string
  357. if rField.FieldType.TypeKind in [tkString, tkLString, tkWString, tkUString] then
  358. {$IFDEF DELPHIRX10_UP}
  359. rValue := DeserializeType(aObject,rField.FieldType.TypeKind,rField.FieldType.Handle,TJsonValue(member).value)
  360. {$ELSE}
  361. rValue := DeserializeType(aObject,rField.FieldType.TypeKind,rField.FieldType.Handle,member.JsonString.ToString)
  362. {$ENDIF}
  363. else rValue := DeserializeType(aObject,rField.FieldType.TypeKind,rField.FieldType.Handle,member.ToJSON);
  364. end;
  365. end;
  366. if not rValue.IsEmpty then rField.SetValue(aRecord.GetReferenceToRawData,rValue);
  367. end;
  368. Result := aRecord;
  369. end;
  370. {$ENDIF}
  371. constructor TRTTIJson.Create(aSerializeLevel : TSerializeLevel; aUseEnumNames : Boolean = True);
  372. begin
  373. fSerializeLevel := aSerializeLevel;
  374. fUseEnumNames := aUseEnumNames;
  375. fUseJsonCaseSense := False;
  376. end;
  377. function TRTTIJson.DeserializeClass(aType: TClass; const aJson: TJSONObject): TObject;
  378. begin
  379. Result := nil;
  380. if (aJson = nil) or ((aJson as TJSONValue) is TJSONNull) or (aJson.Count = 0) then Exit;
  381. Result := aType.Create;
  382. try
  383. Result := DeserializeObject(Result,aJson);
  384. except
  385. on E : Exception do
  386. begin
  387. Result.Free;
  388. raise EJsonDeserializeError.CreateFmt('Deserialize error class "%s" : %s',[aType.ClassName,e.Message]);
  389. end;
  390. end;
  391. end;
  392. function TRTTIJson.DeserializeObject(aObject: TObject; const aJson: TJSONObject): TObject;
  393. var
  394. ctx: TRttiContext;
  395. rType: TRttiType;
  396. rProp: TRttiProperty;
  397. {$IFNDEF FPC}
  398. attr: TCustomAttribute;
  399. {$ENDIF}
  400. propertyname : string;
  401. begin
  402. Result := aObject;
  403. if (aJson = nil) or ((aJson as TJSONValue) is TJSONNull) or (aJson.Count = 0) or (Result = nil) then Exit;
  404. try
  405. rType := ctx.GetType(aObject.ClassInfo);
  406. for rProp in rType.GetProperties do
  407. begin
  408. {$IFNDEF FPC}
  409. if ((fSerializeLevel = slPublicProperty) and (rProp.PropertyType.IsPublicType))
  410. or ((fSerializeLevel = slPublishedProperty) and ((IsPublishedProp(aObject,rProp.Name)) or (rProp.Name = 'List'))) then
  411. {$ENDIF}
  412. begin
  413. if ((rProp.IsWritable) or (rProp.Name = 'List')) and (IsAllowedProperty(aObject,rProp.Name)) then
  414. begin
  415. propertyname := rProp.Name;
  416. {$IFNDEF FPC}
  417. for attr in rProp.GetAttributes do if attr is TCustomNameProperty then propertyname := TCustomNameProperty(attr).Name;
  418. if rProp.Name = 'List' then
  419. begin
  420. Result := DeserializeList(Result,propertyname,aJson);
  421. end
  422. else if (rProp.GetValue(aObject).IsObject) and (IsGenericList(rProp.GetValue(aObject).AsObject)) then
  423. begin
  424. DeserializeList(rProp.GetValue(aObject).AsObject,'List',TJSONObject(aJson.GetValue(propertyname)));
  425. end
  426. else if (not rProp.GetValue(aObject).IsObject) and (IsGenericXArray(rProp.GetValue(aObject){$IFNDEF NEXTGEN}.TypeInfo.Name{$ELSE}.TypeInfo.NameFld.ToString{$ENDIF})) then
  427. begin
  428. DeserializeXArray(Result,rProp.GetValue(aObject),rProp,propertyname,aJson);
  429. end
  430. else
  431. {$ENDIF}
  432. Result := DeserializeProperty(Result,propertyname,rProp,aJson);
  433. end;
  434. end;
  435. end;
  436. except
  437. on E : Exception do
  438. begin
  439. Result.Free;
  440. raise EJsonDeserializeError.CreateFmt('Deserialize error for object "%s" : %s',[aObject.ClassName,e.Message]);
  441. end;
  442. end;
  443. end;
  444. {$IFNDEF FPC}
  445. function TRTTIJson.DeserializeList(aObject: TObject; const aName : string; const aJson: TJSONObject) : TObject;
  446. var
  447. ctx : TRttiContext;
  448. rType : TRttiType;
  449. jarray : TJSONArray;
  450. member : TJsonValue;
  451. rvalue : TValue;
  452. i : Integer;
  453. n : Integer;
  454. rProp : TRttiProperty;
  455. {$IFNDEF DELPHIRX10_UP}
  456. rfield : TRttiField;
  457. {$ENDIF}
  458. begin
  459. Result := aObject;
  460. rType := ctx.GetType(aObject.ClassInfo);
  461. rProp := rType.GetProperty('List');
  462. if rProp = nil then Exit;
  463. member := GetJsonPairValueByName(aJson,aName);
  464. if member = nil then jArray := TJSONObject.ParseJSONValue(aJson.ToJSON) as TJSONArray
  465. else jArray := TJSONObject.ParseJSONValue(member.ToJSON) as TJSONArray;
  466. try
  467. rvalue := DeserializeDynArray(rProp.PropertyType.Handle,Result,jArray);
  468. //i := jarray.Count;
  469. finally
  470. jArray.Free;
  471. end;
  472. if not rValue.IsEmpty then
  473. begin
  474. {$IFDEF DELPHIRX10_UP}
  475. if (TObjectList<TObject>(aObject) <> nil) and (rvalue.IsArray) then
  476. begin
  477. TObjectList<TObject>(aObject).Clear;
  478. n := rvalue.GetArrayLength - 1;
  479. for i := 0 to n do
  480. begin
  481. TObjectList<TObject>(aObject).Add(rvalue.GetArrayElement(i).AsObject);
  482. end;
  483. end;
  484. {$ELSE}
  485. n := 0;
  486. for rfield in rType.GetFields do
  487. begin
  488. if rfield.Name = 'FOwnsObjects' then rfield.SetValue(aObject,True);
  489. //if rfield.Name = 'FCount' then rfield.SetValue(aObject,i);
  490. if rfield.Name = 'FItems' then
  491. begin
  492. //if TList(aObject) <> nil then TList(aObject).Clear;
  493. //rfield.GetValue(aObject).AsObject.Free;// aValue.GetReferenceToRawData)
  494. rfield.SetValue(aObject,rValue);// .SetDynArrayProp(aObject,'fItems',Result);
  495. Break;
  496. end;
  497. end;
  498. rProp := rType.GetProperty('Count');
  499. rProp.SetValue(aObject,n);
  500. {$ENDIF}
  501. end;
  502. end;
  503. {$ENDIF}
  504. {$IFNDEF FPC}
  505. procedure TRTTIJson.DeserializeXArray(Instance : TObject; aRecord : TValue; aProperty : TRttiProperty; const aPropertyName : string; aJson : TJsonObject);
  506. var
  507. ctx : TRttiContext;
  508. rRec : TRttiRecordType;
  509. rfield : TRttiField;
  510. rValue : TValue;
  511. member : TJsonValue;
  512. jArray : TJSONArray;
  513. begin
  514. rRec := ctx.GetType(aRecord.TypeInfo).AsRecord;
  515. rfield := rRec.GetField('fArray');
  516. if rfield <> nil then
  517. begin
  518. rValue := nil;
  519. //member := TJSONPair(aJson.GetValue(rField.Name));
  520. member := GetJsonPairValueByName(aJson,aPropertyName);
  521. if (member <> nil) and (rField.FieldType.TypeKind = tkDynArray) then
  522. begin
  523. jArray := TJSONObject.ParseJSONValue(member.ToJSON) as TJSONArray;
  524. try
  525. rValue := DeserializeDynArray(rField.FieldType.Handle,nil,jArray);
  526. finally
  527. jArray.Free;
  528. end;
  529. end;
  530. end;
  531. if not rValue.IsEmpty then rField.SetValue(aRecord.GetReferenceToRawData,rValue);
  532. aProperty.SetValue(Instance,aRecord);
  533. end;
  534. {$ENDIF}
  535. function TRTTIJson.DeserializeProperty(aObject : TObject; const aName : string; aProperty : TRttiProperty; const aJson : TJSONObject) : TObject;
  536. var
  537. rValue : TValue;
  538. {$IFNDEF FPC}
  539. member : TJsonValue;
  540. {$ELSE}
  541. member : TJsonObject;
  542. {$ENDIF}
  543. objClass: TClass;
  544. jArray : TJSONArray;
  545. json : TJSONObject;
  546. begin
  547. Result := aObject;
  548. rValue := nil;
  549. {$IFNDEF FPC}
  550. //member := TJSONPair(aJson.GetValue(aName));
  551. member := GetJsonPairValueByName(aJson,aName);
  552. {$ELSE}
  553. member := TJsonObject(aJson.Find(aName));
  554. {$ENDIF}
  555. if member <> nil then
  556. begin
  557. case aProperty.PropertyType.TypeKind of
  558. tkDynArray :
  559. begin
  560. {$IFNDEF FPC}
  561. jArray := TJSONObject.ParseJSONValue(member.ToJSON) as TJSONArray;
  562. {$ELSE}
  563. jArray := TJSONArray(TJSONObject.ParseJSONValue(member.ToJSON));
  564. {$ENDIF}
  565. try
  566. {$IFNDEF FPC}
  567. aProperty.SetValue(aObject,DeserializeDynArray(aProperty.PropertyType.Handle,Result,jArray));
  568. {$ELSE}
  569. DeserializeDynArray(aProperty.PropertyType.Handle,aName,Result,jArray);
  570. {$ENDIF}
  571. Exit;
  572. finally
  573. jArray.Free;
  574. end;
  575. end;
  576. tkClass :
  577. begin
  578. //if (member.JsonValue is TJSONObject) then
  579. begin
  580. json := TJsonObject(TJSONObject.ParseJSONValue(member.ToJson));
  581. try
  582. if aProperty.GetValue(aObject).AsObject = nil then
  583. begin
  584. {$IFNDEF FPC}
  585. objClass := aProperty.PropertyType.Handle^.TypeData.ClassType;
  586. rValue := DeserializeClass(objClass,json);
  587. {$ELSE}
  588. objClass := GetObjectPropClass(aObject,aName);
  589. //objClass := GetTypeData(aProperty.PropertyType.Handle)^.ClassType;
  590. rValue := DeserializeClass(objClass,json);
  591. SetObjectProp(aObject,aName,rValue.AsObject);
  592. Exit;
  593. {$ENDIF}
  594. end
  595. else
  596. begin
  597. rValue := DeserializeObject(aProperty.GetValue(aObject).AsObject,json);
  598. Exit;
  599. end;
  600. finally
  601. json.Free;
  602. end;
  603. end
  604. end;
  605. {$IFNDEF FPC}
  606. tkRecord :
  607. begin
  608. if aProperty.GetValue(aObject).TypeInfo = System.TypeInfo(TGUID) then
  609. begin
  610. rValue:=TValue.From<TGUID>(StringToGUID(member.ToJSON.DeQuotedString('"')));
  611. end
  612. else
  613. begin
  614. json := TJSONObject.ParseJSONValue(member.ToJson) as TJSONObject;
  615. try
  616. rValue := DeserializeRecord(aProperty.GetValue(aObject),aObject,json);
  617. finally
  618. json.Free;
  619. end;
  620. end;
  621. end;
  622. {$ENDIF}
  623. else
  624. begin
  625. {$IFNDEF FPC}
  626. //avoid return unicode escaped chars if string
  627. if aProperty.PropertyType.TypeKind in [tkString, tkLString, tkWString, tkUString] then
  628. {$IFDEF DELPHIRX10_UP}
  629. rValue := DeserializeType(aObject,aProperty.PropertyType.TypeKind,aProperty.GetValue(aObject).TypeInfo,TJsonValue(member).value)
  630. {$ELSE}
  631. rValue := DeserializeType(aObject,aProperty.PropertyType.TypeKind,aProperty.GetValue(aObject).TypeInfo,member.JsonString.ToString)
  632. {$ENDIF}
  633. else rValue := DeserializeType(aObject,aProperty.PropertyType.TypeKind,aProperty.GetValue(aObject).TypeInfo,member.ToJSON);
  634. {$ELSE}
  635. rValue := DeserializeType(aObject,aProperty.PropertyType.TypeKind,aName,member.ToJSON);
  636. if not rValue.IsEmpty then SetPropertyValue(aObject,aName,rValue);
  637. {$ENDIF}
  638. end;
  639. end;
  640. {$IFNDEF FPC}
  641. if not rValue.IsEmpty then aProperty.SetValue(Result,rValue);
  642. {$ENDIF}
  643. end;
  644. end;
  645. {$IFNDEF FPC}
  646. function TRTTIJson.DeserializeType(aObject : TObject; aType : TTypeKind; aTypeInfo : PTypeInfo; const aValue: string) : TValue;
  647. var
  648. i : Integer;
  649. value : string;
  650. fsettings : TFormatSettings;
  651. begin
  652. try
  653. value := AnsiDequotedStr(aValue,'"');
  654. case aType of
  655. tkString, tkLString, tkWString, tkUString :
  656. begin
  657. Result := value;
  658. end;
  659. tkChar, tkWChar :
  660. begin
  661. Result := value;
  662. end;
  663. tkInteger :
  664. begin
  665. Result := StrToInt(value);
  666. end;
  667. tkInt64 :
  668. begin
  669. Result := StrToInt64(value);
  670. end;
  671. tkFloat :
  672. begin
  673. if aTypeInfo = TypeInfo(TDateTime) then
  674. begin
  675. Result := JsonDateToDateTime(value);
  676. end
  677. else if aTypeInfo = TypeInfo(TDate) then
  678. begin
  679. Result := StrToDate(value);
  680. end
  681. else if aTypeInfo = TypeInfo(TTime) then
  682. begin
  683. Result := StrToTime(value);
  684. end
  685. else
  686. begin
  687. fsettings := TFormatSettings.Create;
  688. Result := StrToFloat(StringReplace(value,'.',fsettings.DecimalSeparator,[]));
  689. end;
  690. end;
  691. tkEnumeration :
  692. begin
  693. if aTypeInfo = System.TypeInfo(Boolean) then
  694. begin
  695. Result := StrToBool(value);
  696. end
  697. else
  698. begin
  699. //if fUseEnumNames then TValue.Make(GetEnumValue(aTypeInfo,value),aTypeInfo, Result)
  700. // else TValue.Make(StrToInt(value),aTypeInfo, Result);
  701. if not TryStrToInt(value,i) then TValue.Make(GetEnumValue(aTypeInfo,value),aTypeInfo, Result)
  702. else TValue.Make(StrToInt(value),aTypeInfo, Result);
  703. end;
  704. end;
  705. tkSet :
  706. begin
  707. i := StringToSet(aTypeInfo,value);
  708. TValue.Make(@i,aTypeInfo,Result);
  709. end;
  710. else
  711. begin
  712. //raise EclJsonSerializerError.Create('Not supported data type!');
  713. end;
  714. end;
  715. except
  716. on E : Exception do
  717. begin
  718. raise EJsonDeserializeError.CreateFmt('Deserialize error type "%s.%s" : %s',[aObject.ClassName,GetTypeName(aTypeInfo),e.Message]);
  719. end;
  720. end;
  721. end;
  722. {$ELSE}
  723. function TRTTIJson.DeserializeType(aObject : TObject; aType : TTypeKind; const aPropertyName, aValue: string) : TValue;
  724. var
  725. value : string;
  726. propinfo : PPropInfo;
  727. fsettings : TFormatSettings;
  728. begin
  729. try
  730. value := AnsiDequotedStr(aValue,'"');
  731. if value = '' then
  732. begin
  733. Result := nil;
  734. Exit;
  735. end;
  736. propinfo := GetPropInfo(aObject,aPropertyName);
  737. //case propinfo.PropType.Kind of
  738. case aType of
  739. tkString, tkLString, tkWString, tkUString, tkAString :
  740. begin
  741. Result := value;
  742. //SetStrProp(aObject,propinfo,value);
  743. end;
  744. tkChar, tkWChar :
  745. begin
  746. Result := value;
  747. end;
  748. tkInteger :
  749. begin
  750. Result := StrToInt(value);
  751. end;
  752. tkInt64 :
  753. begin
  754. Result := StrToInt64(value);
  755. end;
  756. tkFloat :
  757. begin
  758. if propinfo.PropType = TypeInfo(TDateTime) then
  759. begin
  760. Result := JsonDateToDateTime(value);
  761. end
  762. else if propinfo.PropType = TypeInfo(TDate) then
  763. begin
  764. Result := StrToDate(value);
  765. end
  766. else if propinfo.PropType = TypeInfo(TTime) then
  767. begin
  768. Result := StrToTime(value);
  769. end
  770. else
  771. begin
  772. fsettings := DefaultFormatSettings;
  773. Result := StrToFloat(StringReplace(value,'.',fsettings.DecimalSeparator,[]));
  774. end;
  775. end;
  776. tkEnumeration:
  777. begin
  778. Result := value;
  779. end;
  780. tkBool :
  781. begin
  782. Result := StrToBool(value);
  783. end;
  784. tkSet :
  785. begin
  786. Result := value;
  787. end;
  788. else
  789. begin
  790. //raise EclJsonSerializerError.Create('Not supported data type!');
  791. end;
  792. end;
  793. //if not Result.IsEmpty then SetPropertyValue(aObject,propinfo,Result);
  794. except
  795. on E : Exception do
  796. begin
  797. raise EJsonDeserializeError.CreateFmt('Deserialize error type "%s" : %s',[aObject.ClassName,e.Message]);
  798. end;
  799. end;
  800. end;
  801. {$ENDIF}
  802. function TRTTIJson.IsAllowedProperty(aObject : TObject; const aPropertyName : string) : Boolean;
  803. var
  804. propname : string;
  805. begin
  806. Result := True;
  807. propname := aPropertyName.ToLower;
  808. if IsGenericList(aObject) then
  809. begin
  810. if (propname = 'capacity') or (propname = 'count') or (propname = 'ownsobjects') then Result := False;
  811. end
  812. else if (propname = 'refcount') then Result := False;
  813. end;
  814. function TRTTIJson.IsGenericList(aObject : TObject) : Boolean;
  815. var
  816. cname : string;
  817. begin
  818. if aObject = nil then Exit(False);
  819. cname := aObject.ClassName;
  820. Result := (cname.StartsWith('TObjectList')) or (cname.StartsWith('TList'));
  821. end;
  822. function TRTTIJson.IsGenericXArray(const aClassName : string) : Boolean;
  823. begin
  824. Result := aClassName.StartsWith('TXArray');
  825. end;
  826. function TRTTIJson.GetJsonPairValueByName(aJson: TJSONObject; const aName: string): TJsonValue;
  827. var
  828. candidate : TJSONPair;
  829. i : Integer;
  830. begin
  831. if fUseJsonCaseSense then
  832. begin
  833. Result := aJson.GetValue(aName);
  834. Exit;
  835. end
  836. else
  837. begin
  838. for i := 0 to aJson.Count - 1 do
  839. begin
  840. candidate := aJson.Pairs[I];
  841. if candidate.JsonValue = nil then Exit(nil);
  842. if CompareText(candidate.JsonString{$IFNDEF FPC}.Value{$ENDIF},aName) = 0 then
  843. Exit(candidate.JsonValue);
  844. end;
  845. end;
  846. Result := nil;
  847. end;
  848. function TRTTIJson.GetJsonPairByName(aJson: TJSONObject; const aName: string): TJSONPair;
  849. var
  850. i : Integer;
  851. begin
  852. if fUseJsonCaseSense then
  853. begin
  854. Result := TJSONPair(aJson.GetValue(aName));
  855. Exit;
  856. end
  857. else
  858. begin
  859. if aJson <> nil then
  860. begin
  861. for i := 0 to aJson.Count - 1 do
  862. begin
  863. Result := aJson.Pairs[I];
  864. if Result.JsonValue = nil then Exit(nil);
  865. if CompareText(Result.JsonString{$IFNDEF FPC}.Value{$ENDIF},aName) = 0 then Exit;
  866. end;
  867. end;
  868. end;
  869. Result := nil;
  870. end;
  871. function TRTTIJson.GetPropertyValue(Instance : TObject; const PropertyName : string) : TValue;
  872. var
  873. pinfo : PPropInfo;
  874. begin
  875. Result := nil;
  876. pinfo := GetPropInfo(Instance,PropertyName);
  877. if pinfo = nil then raise EJsonSerializeError.CreateFmt('Property "%s" not found!',[PropertyName]);
  878. case pinfo.PropType^.Kind of
  879. tkInteger : Result := GetOrdProp(Instance,pinfo);
  880. tkInt64 : Result := GetInt64Prop(Instance,PropertyName);
  881. tkFloat : Result := GetFloatProp(Instance,PropertyName);
  882. tkChar : Result := Char(GetOrdProp(Instance,PropertyName));
  883. {$IFDEF FPC}
  884. tkWString : Result := GetWideStrProp(Instance,PropertyName);
  885. tkSString,
  886. tkAString,
  887. {$ELSE}
  888. tkWString,
  889. {$ENDIF}
  890. tkLString : Result := GetStrProp(Instance,pinfo);
  891. {$IFDEF FPC}
  892. tkEnumeration :
  893. begin
  894. if fUseEnumNames then Result := GetEnumName(pinfo.PropType,GetOrdProp(Instance,PropertyName))
  895. else Result := GetOrdProp(Instance,PropertyName);
  896. end;
  897. {$ELSE}
  898. tkEnumeration :
  899. begin
  900. if fUseEnumNames then Result := GetEnumName(@pinfo.PropType,GetOrdProp(Instance,PropertyName))
  901. else Result := GetOrdProp(Instance,PropertyName);
  902. end;
  903. {$ENDIF}
  904. tkSet : Result := GetSetProp(Instance,pinfo,True);
  905. {$IFNDEF FPC}
  906. tkClass :
  907. {$ELSE}
  908. tkBool : Result := Boolean(GetOrdProp(Instance,pinfo));
  909. tkObject :
  910. {$ENDIF} Result := GetObjectProp(Instance,pinfo);
  911. tkDynArray : Result := GetDynArrayProp(Instance,pinfo);
  912. end;
  913. end;
  914. function TRTTIJson.GetPropertyValueFromObject(Instance : TObject; const PropertyName : string) : TValue;
  915. var
  916. ctx : TRttiContext;
  917. rprop : TRttiProperty;
  918. begin
  919. rprop := ctx.GetType(Instance.ClassInfo).GetProperty(PropertyName);
  920. Result := rprop.GetValue(Instance);
  921. end;
  922. {$IFNDEF FPC}
  923. function TRTTIJson.GetFieldValueFromRecord(aValue : TValue; const FieldName : string) : TValue;
  924. var
  925. ctx : TRttiContext;
  926. rec : TRttiRecordType;
  927. rfield : TRttiField;
  928. begin
  929. rec := ctx.GetType(aValue.TypeInfo).AsRecord;
  930. rfield := rec.GetField(FieldName);
  931. if rfield <> nil then Result := rField.GetValue(aValue.GetReferenceToRawData)
  932. else Result := nil;
  933. end;
  934. {$ENDIF}
  935. procedure TRTTIJson.SetPropertyValue(Instance : TObject; const PropertyName : string; aValue : TValue);
  936. var
  937. pinfo : PPropInfo;
  938. begin
  939. pinfo := GetPropInfo(Instance,PropertyName);
  940. SetPropertyValue(Instance,pinfo,aValue);
  941. end;
  942. procedure TRTTIJson.SetPropertyValue(Instance : TObject; aPropInfo : PPropInfo; aValue : TValue);
  943. begin
  944. case aPropInfo.PropType^.Kind of
  945. tkInteger : SetOrdProp(Instance,aPropInfo,aValue.AsInteger);
  946. tkInt64 : SetInt64Prop(Instance,aPropInfo,aValue.AsInt64);
  947. tkFloat : SetFloatProp(Instance,aPropInfo,aValue.AsExtended);
  948. tkChar : SetOrdProp(Instance,aPropInfo,aValue.AsOrdinal);
  949. {$IFDEF FPC}
  950. tkWString : SetWideStrProp(Instance,aPropInfo,aValue.AsString);
  951. tkSString,
  952. tkAString,
  953. {$ELSE}
  954. tkWString,
  955. {$ENDIF}
  956. tkLString : SetStrProp(Instance,aPropInfo,aValue.AsString);
  957. {$IFDEF FPC}
  958. tkBool : SetOrdProp(Instance,aPropInfo,aValue.AsOrdinal);
  959. tkSet : LoadSetProperty(Instance,aPropInfo,aValue.AsString);
  960. {$ENDIF}
  961. tkEnumeration : SetEnumProp(Instance,aPropInfo,aValue.AsString);
  962. {$IFNDEF FPC}
  963. tkClass :
  964. {$ELSE}
  965. tkObject :
  966. {$ENDIF} SetObjectProp(Instance,aPropInfo,aValue.AsObject);
  967. end;
  968. end;
  969. {$IFDEF FPC}
  970. procedure TRTTIJson.LoadSetProperty(aInstance : TObject; aPropInfo: PPropInfo; const aValue: string);
  971. type
  972. TCardinalSet = set of 0..SizeOf(Cardinal) * 8 - 1;
  973. const
  974. Delims = [' ', ',', '[', ']'];
  975. var
  976. TypeInfo: PTypeInfo;
  977. W: Cardinal;
  978. I, N: Integer;
  979. Count: Integer;
  980. EnumName: string;
  981. begin
  982. W := 0;
  983. TypeInfo := GetTypeData(GetPropType(aPropInfo))^.CompType;
  984. Count := WordCount(aValue, Delims);
  985. for N := 1 to Count do
  986. begin
  987. EnumName := ExtractWord(N, aValue, Delims);
  988. try
  989. I := GetEnumValue(TypeInfo, EnumName);
  990. if I >= 0 then Include(TCardinalSet(W),I);
  991. except
  992. end;
  993. end;
  994. SetOrdProp(aInstance,aPropInfo,W);
  995. end;
  996. {$ENDIF}
  997. function TRTTIJson.Serialize(aObject: TObject): TJSONObject;
  998. var
  999. ctx: TRttiContext;
  1000. {$IFNDEF FPC}
  1001. attr : TCustomAttribute;
  1002. comment : string;
  1003. {$ENDIF}
  1004. rType: TRttiType;
  1005. rProp: TRttiProperty;
  1006. jpair : TJSONPair;
  1007. ExcludeSerialize : Boolean;
  1008. propertyname : string;
  1009. propvalue : TValue;
  1010. begin
  1011. if (aObject = nil) then
  1012. begin
  1013. Result := nil;
  1014. Exit;
  1015. end;
  1016. Result := TJSONObject.Create;
  1017. try
  1018. rType := ctx.GetType(aObject.ClassInfo);
  1019. //s := rType.ToString;
  1020. for rProp in rType.GetProperties do
  1021. begin
  1022. ExcludeSerialize := False;
  1023. propertyname := rProp.Name;
  1024. {$IFNDEF FPC}
  1025. comment := '';
  1026. for attr in rProp.GetAttributes do
  1027. begin
  1028. if attr is TNotSerializableProperty then ExcludeSerialize := True
  1029. else if attr is TCommentProperty then comment := TCommentProperty(attr).Comment
  1030. else if attr is TCustomNameProperty then propertyname := TCustomNameProperty(attr).Name;
  1031. end;
  1032. if ((fSerializeLevel = slPublicProperty) and (rProp.PropertyType.IsPublicType))
  1033. or ((fSerializeLevel = slPublishedProperty) and ((IsPublishedProp(aObject,rProp.Name)) or (rProp.Name = 'List'))) then
  1034. {$ENDIF}
  1035. begin
  1036. if (IsAllowedProperty(aObject,propertyname)) and (not ExcludeSerialize) then
  1037. begin
  1038. //add comment as pair
  1039. {$IFNDEF FPC}
  1040. if comment <> '' then Result.AddPair(TJSONPair.Create('#Comment#->'+propertyname,Comment));
  1041. {$ENDIF}
  1042. begin
  1043. propvalue := rProp.GetValue(aObject);
  1044. if (propvalue.IsObject) and (IsGenericList(propvalue.AsObject)) then
  1045. begin
  1046. jpair := Serialize(propertyname,GetPropertyValueFromObject(propvalue.AsObject,'List'));
  1047. end
  1048. {$IFNDEF FPC}
  1049. else if (not propvalue.IsObject) and (IsGenericXArray(propvalue{$IFNDEF NEXTGEN}.TypeInfo.Name{$ELSE}.TypeInfo.NameFld.ToString{$ENDIF})) then
  1050. begin
  1051. jpair := Serialize(propertyname,GetFieldValueFromRecord(propvalue,'fArray'));
  1052. end
  1053. {$ENDIF}
  1054. else
  1055. begin
  1056. {$IFNDEF FPC}
  1057. jpair := Serialize(propertyname,propvalue);
  1058. {$ELSE}
  1059. jpair := Serialize(aObject,rProp.PropertyType.TypeKind,propertyname);
  1060. {$ENDIF}
  1061. end;
  1062. //s := jpair.JsonValue.ToString;
  1063. if jpair <> nil then
  1064. begin
  1065. Result.AddPair(jpair);
  1066. end
  1067. else jpair.Free;
  1068. end;
  1069. //Result.AddPair(Serialize(rProp.Name,rProp.GetValue(aObject)));
  1070. //s := Result.ToJSON;
  1071. end;
  1072. end;
  1073. end;
  1074. except
  1075. on E : Exception do
  1076. begin
  1077. Result.Free;
  1078. raise EJsonSerializeError.CreateFmt('Serialize error object "%s" : %s',[aObject.ClassName,e.Message]);
  1079. end;
  1080. end;
  1081. end;
  1082. function TRTTIJson.GetValue(aAddr: Pointer; aType: TRTTIType): TValue;
  1083. begin
  1084. TValue.Make(aAddr,aType.Handle,Result);
  1085. end;
  1086. function TRTTIJson.GetValue(aAddr: Pointer; aTypeInfo: PTypeInfo): TValue;
  1087. begin
  1088. TValue.Make(aAddr,aTypeInfo,Result);
  1089. end;
  1090. {$IFNDEF FPC}
  1091. function TRTTIJson.Serialize(const aName : string; aValue : TValue) : TJSONPair;
  1092. var
  1093. ctx: TRttiContext;
  1094. rRec : TRttiRecordType;
  1095. rField : TRttiField;
  1096. rDynArray : TRTTIDynamicArrayType;
  1097. json : TJSONObject;
  1098. jArray : TJSONArray;
  1099. jPair : TJSONPair;
  1100. jValue : TJSONValue;
  1101. i : Integer;
  1102. begin
  1103. Result := TJSONPair.Create(aName,nil);
  1104. //Result.JsonString := TJSONString(aName);
  1105. try
  1106. case avalue.Kind of
  1107. tkDynArray :
  1108. begin
  1109. jArray := TJSONArray.Create;
  1110. rDynArray := ctx.GetType(aValue.TypeInfo) as TRTTIDynamicArrayType;
  1111. for i := 0 to aValue.GetArrayLength - 1 do
  1112. begin
  1113. if not GetValue(PPByte(aValue.GetReferenceToRawData)^ + rDynArray.ElementType.TypeSize * i, rDynArray.ElementType).IsEmpty then
  1114. begin
  1115. jValue := nil;
  1116. jPair := Serialize(aName,GetValue(PPByte(aValue.GetReferenceToRawData)^ + rDynArray.ElementType.TypeSize * i, rDynArray.ElementType));
  1117. try
  1118. //jValue := TJsonValue(jPair.JsonValue.Clone);
  1119. jValue := jPair.JsonValue;
  1120. if jValue <> nil then
  1121. begin
  1122. jArray.AddElement(jValue);
  1123. jPair.JsonValue.Owned := False;
  1124. end;
  1125. finally
  1126. jPair.Free;
  1127. if jValue <> nil then jValue.Owned := True;
  1128. end;
  1129. end;
  1130. end;
  1131. Result.JsonValue := jArray;
  1132. end;
  1133. tkClass :
  1134. begin
  1135. Result.JsonValue := TJSONValue(Serialize(aValue.AsObject));
  1136. end;
  1137. tkString, tkLString, tkWString, tkUString :
  1138. begin
  1139. Result.JsonValue := TJSONString.Create(aValue.AsString);
  1140. end;
  1141. tkChar, tkWChar :
  1142. begin
  1143. Result.JsonValue := TJSONString.Create(aValue.AsString);
  1144. end;
  1145. tkInteger :
  1146. begin
  1147. Result.JsonValue := TJSONNumber.Create(aValue.AsInteger);
  1148. end;
  1149. tkInt64 :
  1150. begin
  1151. Result.JsonValue := TJSONNumber.Create(aValue.AsInt64);
  1152. end;
  1153. tkFloat :
  1154. begin
  1155. if aValue.TypeInfo = TypeInfo(TDateTime) then
  1156. begin
  1157. Result.JsonValue := TJSONString.Create(DateTimeToJsonDate(aValue.AsExtended));
  1158. end
  1159. else if aValue.TypeInfo = TypeInfo(TDate) then
  1160. begin
  1161. Result.JsonValue := TJSONString.Create(DateToStr(aValue.AsExtended));
  1162. end
  1163. else if aValue.TypeInfo = TypeInfo(TTime) then
  1164. begin
  1165. Result.JsonValue := TJSONString.Create(TimeToStr(aValue.AsExtended));
  1166. end
  1167. else
  1168. begin
  1169. Result.JsonValue := TJSONNumber.Create(aValue.AsExtended);
  1170. end;
  1171. end;
  1172. tkEnumeration :
  1173. begin
  1174. if (aValue.TypeInfo = System.TypeInfo(Boolean)) then
  1175. begin
  1176. {$IFDEF DELPHIRX10_UP}
  1177. Result.JsonValue := TJSONBool.Create(aValue.AsBoolean);
  1178. {$ELSE}
  1179. if aValue.AsBoolean then Result.JsonValue := TJsonTrue.Create
  1180. else Result.JsonValue := TJsonFalse.Create;
  1181. {$ENDIF}
  1182. end
  1183. else
  1184. begin
  1185. //Result.JsonValue := TJSONString.Create(GetEnumName(aValue.TypeInfo,aValue.AsOrdinal));
  1186. if fUseEnumNames then Result.JsonValue := TJSONString.Create(aValue.ToString)
  1187. else Result.JsonValue := TJSONNumber.Create(GetEnumValue(aValue.TypeInfo,aValue.ToString));
  1188. end;
  1189. end;
  1190. tkSet :
  1191. begin
  1192. Result.JsonValue := TJSONString.Create(aValue.ToString);
  1193. end;
  1194. tkRecord :
  1195. begin
  1196. rRec := ctx.GetType(aValue.TypeInfo).AsRecord;
  1197. if aValue.TypeInfo = System.TypeInfo(TGUID) then
  1198. begin
  1199. Result.JsonValue := TJSONString.Create(GUIDToString(aValue.AsType<TGUID>));
  1200. end
  1201. else
  1202. begin
  1203. json := TJSONObject.Create;
  1204. for rField in rRec.GetFields do
  1205. begin
  1206. json.AddPair(Serialize(rField.name,rField.GetValue(aValue.GetReferenceToRawData)));
  1207. end;
  1208. Result.JsonValue := json;
  1209. end;
  1210. end;
  1211. tkVariant :
  1212. begin
  1213. case VarType(aValue.AsVariant) and VarTypeMask of
  1214. varInteger, varInt64 : Result.JsonValue := TJSONNumber.Create(aValue.AsInteger);
  1215. varString, varUString, varEmpty : Result.JsonValue := TJSONString.Create(aValue.AsString);
  1216. varDouble : Result.JsonValue := TJSONNumber.Create(aValue.AsExtended);
  1217. end;
  1218. end;
  1219. tkMethod, tkPointer, tkClassRef ,tkInterface, tkProcedure :
  1220. begin
  1221. //skip these properties
  1222. //FreeAndNil(Result);
  1223. end
  1224. else
  1225. begin
  1226. raise EJsonSerializeError.CreateFmt(cNotSupportedDataType,[aName,GetTypeName(aValue.TypeInfo)]);
  1227. end;
  1228. end;
  1229. if Result.JsonValue = nil then Result.JsonValue := TJSONNull.Create;
  1230. except
  1231. on E : Exception do
  1232. begin
  1233. Result.Free;
  1234. raise EJsonSerializeError.CreateFmt('Serialize error class "%s.%s" : %s',[aName,aValue.ToString,e.Message]);
  1235. end;
  1236. end;
  1237. end;
  1238. {$ELSE}
  1239. function TRTTIJson.GetPropType(aPropInfo: PPropInfo): PTypeInfo;
  1240. begin
  1241. Result := aPropInfo^.PropType;
  1242. end;
  1243. function TRTTIJson.FloatProperty(aObject : TObject; aPropInfo: PPropInfo): string;
  1244. const
  1245. Precisions: array[TFloatType] of Integer = (7, 15, 18, 18, 19);
  1246. var
  1247. fsettings : TFormatSettings;
  1248. begin
  1249. fsettings := FormatSettings;
  1250. Result := StringReplace(FloatToStrF(GetFloatProp(aObject, aPropInfo), ffGeneral,
  1251. Precisions[GetTypeData(GetPropType(aPropInfo))^.FloatType],0),
  1252. '.',fsettings.DecimalSeparator,[rfReplaceAll]);
  1253. end;
  1254. function TRTTIJson.Serialize(const aName : string; aValue : TValue) : TJSONPair;
  1255. begin
  1256. Result := TJSONPair.Create(aName,nil);
  1257. //Result.JsonString := TJSONString(aName);
  1258. try
  1259. case avalue.Kind of
  1260. tkClass :
  1261. begin
  1262. Result.JsonValue := TJSONValue(Serialize(aValue.AsObject));
  1263. end;
  1264. tkString, tkLString, tkWString, tkUString :
  1265. begin
  1266. Result.JsonValue := TJSONString.Create(aValue.AsString);
  1267. end;
  1268. tkChar, tkWChar :
  1269. begin
  1270. Result.JsonValue := TJSONString.Create(aValue.AsString);
  1271. end;
  1272. tkInteger :
  1273. begin
  1274. Result.JsonValue := TJSONNumber.Create(aValue.AsInteger);
  1275. end;
  1276. tkInt64 :
  1277. begin
  1278. Result.JsonValue := TJSONNumber.Create(aValue.AsInt64);
  1279. end;
  1280. tkFloat :
  1281. begin
  1282. if aValue.TypeInfo = TypeInfo(TDateTime) then
  1283. begin
  1284. Result.JsonValue := TJSONString.Create(DateTimeToJsonDate(aValue.AsExtended));
  1285. end
  1286. else if aValue.TypeInfo = TypeInfo(TDate) then
  1287. begin
  1288. Result.JsonValue := TJSONString.Create(DateToStr(aValue.AsExtended));
  1289. end
  1290. else if aValue.TypeInfo = TypeInfo(TTime) then
  1291. begin
  1292. Result.JsonValue := TJSONString.Create(TimeToStr(aValue.AsExtended));
  1293. end
  1294. else
  1295. begin
  1296. Result.JsonValue := TJSONNumber.Create(aValue.AsExtended);
  1297. end;
  1298. end;
  1299. tkEnumeration :
  1300. begin
  1301. if (aValue.TypeInfo = System.TypeInfo(Boolean)) then
  1302. begin
  1303. Result.JsonValue := TJSONBool.Create(aValue.AsBoolean);
  1304. end
  1305. else
  1306. begin
  1307. //Result.JsonValue := TJSONString.Create(GetEnumName(aValue.TypeInfo,aValue.AsOrdinal));
  1308. if fUseEnumNames then Result.JsonValue := TJSONString.Create(aValue.ToString)
  1309. else Result.JsonValue := TJSONNumber.Create(GetEnumValue(aValue.TypeInfo,aValue.ToString));
  1310. end;
  1311. end;
  1312. tkSet :
  1313. begin
  1314. Result.JsonValue := TJSONString.Create(aValue.ToString);
  1315. end;
  1316. else
  1317. begin
  1318. //raise EJsonDeserializeError.CreateFmt('Not supported type "%s":%d',[aName,Integer(aValue.Kind)]);
  1319. end;
  1320. end;
  1321. if Result.JsonValue = nil then Result.JsonValue := TJSONNull.Create;
  1322. except
  1323. Result.Free;
  1324. end;
  1325. end;
  1326. function TRTTIJson.Serialize(aObject : TObject; aType : TTypeKind; const aPropertyName : string) : TJSONPair;
  1327. var
  1328. propinfo : PPropInfo;
  1329. jArray : TJsonArray;
  1330. jPair : TJsonPair;
  1331. jValue : TJsonValue;
  1332. i : Integer;
  1333. pArr : Pointer;
  1334. rValue : TValue;
  1335. rItemValue : TValue;
  1336. len : Integer;
  1337. begin
  1338. try
  1339. Result := TJSONPair.Create(aPropertyName,nil);
  1340. propinfo := GetPropInfo(aObject,aPropertyName);
  1341. //case propinfo.PropType.Kind of
  1342. case aType of
  1343. tkDynArray :
  1344. begin
  1345. len := 0;
  1346. jArray := TJSONArray.Create;
  1347. try
  1348. pArr := GetDynArrayProp(aObject,aPropertyName);
  1349. TValue.Make(@pArr,propinfo.PropType, rValue);
  1350. if rValue.IsArray then
  1351. begin
  1352. len := rValue.GetArrayLength;
  1353. for i := 0 to len - 1 do
  1354. begin
  1355. rItemValue := rValue.GetArrayElement(i);
  1356. jPair := Serialize(aPropertyName,rItemValue);
  1357. try
  1358. //jValue := TJsonValue(jPair.JsonValue.Clone);
  1359. jValue := jPair.JsonValue;
  1360. jArray.Add(jValue);
  1361. //jPair.JsonValue.Owned := False;
  1362. finally
  1363. jPair.Free;
  1364. //jValue.Owned := True;
  1365. end;
  1366. end;
  1367. end;
  1368. Result.JsonValue := jArray;
  1369. finally
  1370. //DynArrayClear(pArr,propinfo.PropType);
  1371. pArr := nil;
  1372. end;
  1373. end;
  1374. tkClass :
  1375. begin
  1376. Result.JsonValue := TJSONValue(Serialize(GetObjectProp(aObject,aPropertyName)));
  1377. end;
  1378. tkString, tkLString, tkWString, tkUString, tkAString :
  1379. begin
  1380. Result.JsonValue := TJSONString.Create(GetStrProp(aObject,aPropertyName));
  1381. end;
  1382. tkChar, tkWChar :
  1383. begin
  1384. Result.JsonValue := TJSONString.Create(Char(GetOrdProp(aObject,aPropertyName)));
  1385. end;
  1386. tkInteger :
  1387. begin
  1388. Result.JsonValue := TJSONNumber.Create(GetOrdProp(aObject,aPropertyName));
  1389. end;
  1390. tkInt64 :
  1391. begin
  1392. Result.JsonValue := TJSONNumber.Create(GetOrdProp(aObject,aPropertyName));
  1393. end;
  1394. tkFloat :
  1395. begin
  1396. if propinfo.PropType = TypeInfo(TDateTime) then
  1397. begin
  1398. Result.JsonValue := TJSONString.Create(DateTimeToJsonDate(GetFloatProp(aObject,aPropertyName)));
  1399. end
  1400. else if propinfo.PropType = TypeInfo(TDate) then
  1401. begin
  1402. Result.JsonValue := TJSONString.Create(DateToStr(GetFloatProp(aObject,aPropertyName)));
  1403. end
  1404. else if propinfo.PropType = TypeInfo(TTime) then
  1405. begin
  1406. Result.JsonValue := TJSONString.Create(TimeToStr(GetFloatProp(aObject,aPropertyName)));
  1407. end
  1408. else
  1409. begin
  1410. //Result.JsonValue := TJsonFloatNumber.Create(GetFloatProp(aObject,aPropertyName));
  1411. Result.JsonValue := TJsonFloatNumber.Create(StrToFloat(FloatProperty(aObject,propinfo)));
  1412. end;
  1413. end;
  1414. tkEnumeration,tkBool :
  1415. begin
  1416. if (propinfo.PropType = System.TypeInfo(Boolean)) then
  1417. begin
  1418. Result.JsonValue := TJSONBool.Create(Boolean(GetOrdProp(aObject,aPropertyName)));
  1419. end
  1420. else
  1421. begin
  1422. if fUseEnumNames then Result.JsonValue := TJSONString.Create(GetEnumName(propinfo.PropType,GetOrdProp(aObject,aPropertyName)))
  1423. else Result.JsonValue := TJSONNumber.Create(GetOrdProp(aObject,aPropertyName));
  1424. //Result.JsonValue := TJSONString.Create(aValue.ToString);
  1425. end;
  1426. end;
  1427. tkSet :
  1428. begin
  1429. Result.JsonValue := TJSONString.Create(GetSetProp(aObject,aPropertyName));
  1430. end;
  1431. {$IFNDEF FPC}
  1432. tkRecord :
  1433. begin
  1434. rRec := ctx.GetType(aValue.TypeInfo).AsRecord;
  1435. json := TJSONObject.Create;
  1436. for rField in rRec.GetFields do
  1437. begin
  1438. json.AddPair(Serialize(rField.name,rField.GetValue(aValue.GetReferenceToRawData)));
  1439. end;
  1440. Result.JsonValue := json;
  1441. end;
  1442. {$ENDIF}
  1443. tkMethod, tkPointer, tkClassRef ,tkInterface, tkProcedure :
  1444. begin
  1445. //skip these properties
  1446. //FreeAndNil(Result);
  1447. end
  1448. else
  1449. begin
  1450. //raise EJsonDeserializeError.CreateFmt('Not supported type "%s":%d',[aName,Integer(aValue.Kind)]);
  1451. end;
  1452. end;
  1453. if Result.JsonValue = nil then Result.JsonValue := TJSONNull.Create;
  1454. except
  1455. on E : Exception do
  1456. begin
  1457. Result.Free;
  1458. {$IFNDEF FPC}
  1459. raise EJsonSerializeError.CreateFmt('Serialize error class "%s.%s" : %s',[aName,aValue.ToString,e.Message]);
  1460. {$ENDIF}
  1461. end;
  1462. end;
  1463. end;
  1464. {$ENDIF}
  1465. { TJsonSerializer}
  1466. constructor TJsonSerializer.Create(aSerializeLevel: TSerializeLevel; aUseEnumNames : Boolean = True);
  1467. begin
  1468. {$IFDEF FPC}
  1469. if aSerializeLevel = TSerializeLevel.slPublicProperty then raise EJsonSerializeError.Create('FreePascal RTTI only supports published properties');
  1470. {$ENDIF}
  1471. fSerializeLevel := aSerializeLevel;
  1472. fUseEnumNames := aUseEnumNames;
  1473. fUseJsonCaseSense := False;
  1474. fRTTIJson := TRTTIJson.Create(aSerializeLevel,aUseEnumNames);
  1475. fRTTIJson.UseJsonCaseSense := fUseJsonCaseSense;
  1476. end;
  1477. destructor TJsonSerializer.Destroy;
  1478. begin
  1479. fRTTIJson.Free;
  1480. inherited;
  1481. end;
  1482. function TJsonSerializer.JsonToObject(aType: TClass; const aJson: string): TObject;
  1483. var
  1484. json: TJSONObject;
  1485. begin
  1486. {$IFDEF DELPHIRX10_UP}
  1487. json := TJSONObject.ParseJSONValue(aJson,True) as TJSONObject;
  1488. {$ELSE}
  1489. {$IFDEF FPC}
  1490. json := TJSONObject(TJSONObject.ParseJSONValue(aJson,True));
  1491. {$ELSE}
  1492. json := TJsonObject.ParseJSONValue(TEncoding.UTF8.GetBytes(aJson),0,True) as TJSONObject;
  1493. {$ENDIF}
  1494. {$ENDIF}
  1495. try
  1496. Result := fRTTIJson.DeserializeClass(aType,json);
  1497. finally
  1498. json.Free;
  1499. end;
  1500. end;
  1501. function TJsonSerializer.JsonToObject(aObject: TObject; const aJson: string): TObject;
  1502. var
  1503. json: TJSONObject;
  1504. begin;
  1505. {$IFDEF DELPHIRX10_UP}
  1506. json := TJSONObject.ParseJSONValue(aJson,True) as TJSONObject;
  1507. {$ELSE}
  1508. {$IFDEF FPC}
  1509. json := TJSONObject(TJSONObject.ParseJSONValue(aJson,True));
  1510. {$ELSE}
  1511. json := TJsonObject.ParseJSONValue(TEncoding.UTF8.GetBytes(aJson),0,True) as TJSONObject;
  1512. {$ENDIF}
  1513. {$ENDIF}
  1514. try
  1515. Result := fRTTIJson.DeserializeObject(aObject,json);
  1516. finally
  1517. json.Free;
  1518. end;
  1519. end;
  1520. function TJsonSerializer.ObjectToJson(aObject : TObject; aIndent : Boolean = False): string;
  1521. var
  1522. json: TJSONObject;
  1523. begin
  1524. json := fRTTIJson.Serialize(aObject);
  1525. try
  1526. if aIndent then Result := TJsonUtils.JsonFormat(json.ToJSON)
  1527. else Result := json.ToJSON;
  1528. finally
  1529. json.Free;
  1530. end;
  1531. end;
  1532. function TJsonSerializer.ObjectToJsonString(aObject : TObject; aIndent : Boolean = False): string;
  1533. var
  1534. json: TJSONObject;
  1535. begin
  1536. json := fRTTIJson.Serialize(aObject);
  1537. try
  1538. if aIndent then Result := TJsonUtils.JsonFormat(json.ToString)
  1539. else Result := json.ToString;
  1540. finally
  1541. json.Free;
  1542. end;
  1543. end;
  1544. {$IFNDEF FPC}
  1545. function TJsonSerializer.ValueToJson(aValue: TValue; aIndent: Boolean): string;
  1546. var
  1547. json: TJSONObject;
  1548. begin
  1549. json := TJSONObject.Create.AddPair(fRTTIJson.Serialize('value',aValue));
  1550. try
  1551. {$IFDEF DELPHI103_UP}
  1552. if aIndent then Result := TJsonUtils.JsonFormat(json.P['value'].ToJSON)
  1553. else Result := json.P['value'].ToJSON;
  1554. {$ELSE}
  1555. if aIndent then Result := TJsonUtils.JsonFormat(json.GetValue('value').ToJSON)
  1556. else Result := json.GetValue('value').ToJSON;
  1557. {$ENDIF}
  1558. finally
  1559. json.Free;
  1560. end;
  1561. end;
  1562. function TJsonSerializer.ValueToJsonString(aValue: TValue; aIndent: Boolean): string;
  1563. var
  1564. json: TJSONObject;
  1565. begin
  1566. json := TJSONObject.Create.AddPair(fRTTIJson.Serialize('value',aValue));
  1567. try
  1568. {$IFDEF DELPHI103_UP}
  1569. if aIndent then Result := TJsonUtils.JsonFormat(json.P['value'].ToJSON)
  1570. else Result := json.P['value'].ToJSON;
  1571. {$ELSE}
  1572. if aIndent then Result := TJsonUtils.JsonFormat(json.GetValue('value').ToJSON)
  1573. else Result := json.GetValue('value').ToJSON;
  1574. {$ENDIF}
  1575. finally
  1576. json.Free;
  1577. end;
  1578. end;
  1579. function TJsonSerializer.ArrayToJson<T>(aArray: TArray<T>; aIndent: Boolean): string;
  1580. var
  1581. json: TJSONObject;
  1582. begin
  1583. json := TJSONObject.Create.AddPair(fRTTIJson.Serialize('array',TValue.From<TArray<T>>(aArray)));
  1584. try
  1585. {$IFDEF DELPHI103_UP}
  1586. if aIndent then Result := TJsonUtils.JsonFormat(json.P['array'].ToJSON)
  1587. else Result := json.P['array'].ToJSON;
  1588. {$ELSE}
  1589. if aIndent then Result := TJsonUtils.JsonFormat(json.GetValue('array').ToJSON)
  1590. else Result := json.GetValue('array').ToJSON;
  1591. {$ENDIF}
  1592. finally
  1593. json.Free;
  1594. end;
  1595. end;
  1596. function TJsonSerializer.ArrayToJsonString<T>(aArray: TArray<T>; aIndent: Boolean): string;
  1597. var
  1598. json: TJSONObject;
  1599. begin
  1600. json := TJSONObject.Create.AddPair(fRTTIJson.Serialize('array',TValue.From<TArray<T>>(aArray)));
  1601. try
  1602. {$IFDEF DELPHI103_UP}
  1603. if aIndent then Result := TJsonUtils.JsonFormat(json.P['array'].ToJSON)
  1604. else Result := json.P['array'].ToJSON;
  1605. {$ELSE}
  1606. if aIndent then Result := TJsonUtils.JsonFormat(json.GetValue('array').ToJSON)
  1607. else Result := json.GetValue('array').ToJSON;
  1608. {$ENDIF}
  1609. finally
  1610. json.Free;
  1611. end;
  1612. end;
  1613. function TJsonSerializer.JsonToArray<T>(const aJson: string): TArray<T>;
  1614. var
  1615. jarray: TJSONArray;
  1616. value : TValue;
  1617. begin;
  1618. {$If Defined(FPC) OR Defined(DELPHIRX10_UP)}
  1619. jarray := TJSONObject.ParseJSONValue(aJson,True) as TJSONArray;
  1620. {$ELSE}
  1621. jarray := TJsonObject.ParseJSONValue(TEncoding.UTF8.GetBytes(aJson),0,True) as TJSONArray;
  1622. {$ENDIF}
  1623. try
  1624. value := fRTTIJson.DeserializeDynArray(PTypeInfo(TypeInfo(TArray<T>)),nil,jarray);
  1625. Result := value.AsType<TArray<T>>;
  1626. finally
  1627. jarray.Free;
  1628. end;
  1629. end;
  1630. {$ELSE}
  1631. function TJsonSerializer.ValueToJson(aValue: TValue; aIndent: Boolean): string;
  1632. var
  1633. json: TJSONObject;
  1634. begin
  1635. json := TJSONObject.Create;
  1636. json.AddPair(fRTTIJson.Serialize('value',aValue));
  1637. try
  1638. if aIndent then Result := TJsonUtils.JsonFormat(json.Get('value').ToJSON)
  1639. else Result := json.Get('value').ToJSON;
  1640. finally
  1641. json.Free;
  1642. end;
  1643. end;
  1644. function TJsonSerializer.ValueToJsonString(aValue: TValue; aIndent: Boolean): string;
  1645. var
  1646. json: TJSONObject;
  1647. begin
  1648. json := TJSONObject.Create;
  1649. json.AddPair(fRTTIJson.Serialize('value',aValue));
  1650. try
  1651. if aIndent then Result := TJsonUtils.JsonFormat(json.Get('value').ToString)
  1652. else Result := json.Get('value').ToString;
  1653. finally
  1654. json.Free;
  1655. end;
  1656. end;
  1657. function TJsonSerializer.ArrayToJson<T>(aArray: TArray<T>; aIndent: Boolean): string;
  1658. var
  1659. json: TJSONObject;
  1660. begin
  1661. json := TJSONObject.Create;
  1662. json.AddPair(fRTTIJson.Serialize('array',TValue.From<TArray<T>>(aArray)));
  1663. try
  1664. if aIndent then Result := TJsonUtils.JsonFormat(json.Get('array').ToJSON)
  1665. else Result := json.Get('array').ToJSON;
  1666. finally
  1667. json.Free;
  1668. end;
  1669. end;
  1670. function TJsonSerializer.ArrayToJsonString<T>(aArray: TArray<T>; aIndent: Boolean): string;
  1671. var
  1672. json: TJSONObject;
  1673. begin
  1674. json := TJSONObject.Create;
  1675. json.AddPair(fRTTIJson.Serialize('array',TValue.From<TArray<T>>(aArray)));
  1676. try
  1677. if aIndent then Result := TJsonUtils.JsonFormat(json.Get('array').ToString)
  1678. else Result := json.Get('array').ToString;
  1679. finally
  1680. json.Free;
  1681. end;
  1682. end;
  1683. {$ENDIF}
  1684. procedure TJsonSerializer.SetUseEnumNames(const Value: Boolean);
  1685. begin
  1686. fUseEnumNames := Value;
  1687. if Assigned(fRTTIJson) then fRTTIJson.UseEnumNames := Value;
  1688. end;
  1689. procedure TJsonSerializer.SetUseJsonCaseSense(const Value: Boolean);
  1690. begin
  1691. fUseJsonCaseSense := Value;
  1692. if Assigned(fRTTIJson) then fRTTIJson.UseJsonCaseSense := Value;
  1693. end;
  1694. {$IFNDEF FPC}
  1695. { TCommentProperty }
  1696. constructor TCommentProperty.Create(const aComment: string);
  1697. begin
  1698. fComment := aComment;
  1699. end;
  1700. { TCustomNameProperty }
  1701. constructor TCustomNameProperty.Create(const aName: string);
  1702. begin
  1703. fName := aName;
  1704. end;
  1705. {$ENDIF}
  1706. end.