Quick.Json.Serializer.pas 55 KB

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