Quick.Json.Serializer.pas 60 KB

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