Neon.Core.Persistence.JSON.pas 54 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820
  1. {******************************************************************************}
  2. { }
  3. { Neon: Serialization Library for Delphi }
  4. { Copyright (c) 2018-2019 Paolo Rossi }
  5. { https://github.com/paolo-rossi/neon-library }
  6. { }
  7. {******************************************************************************}
  8. { }
  9. { Licensed under the Apache License, Version 2.0 (the "License"); }
  10. { you may not use this file except in compliance with the License. }
  11. { You may obtain a copy of the License at }
  12. { }
  13. { http://www.apache.org/licenses/LICENSE-2.0 }
  14. { }
  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. {******************************************************************************}
  22. unit Neon.Core.Persistence.JSON;
  23. interface
  24. {$I Neon.inc}
  25. uses
  26. System.SysUtils, System.Classes, System.Rtti, System.SyncObjs,
  27. System.TypInfo, System.Generics.Collections, System.JSON,
  28. Neon.Core.Types,
  29. Neon.Core.Attributes,
  30. Neon.Core.Persistence,
  31. Neon.Core.DynamicTypes,
  32. Neon.Core.Utils;
  33. type
  34. /// <summary>
  35. /// JSON Serializer class
  36. /// </summary>
  37. TNeonSerializerJSON = class(TNeonBase, ISerializerContext)
  38. private
  39. /// <summary>
  40. /// Writer for members of objects and records
  41. /// </summary>
  42. procedure WriteMembers(AType: TRttiType; AInstance: Pointer; AResult: TJSONValue);
  43. private
  44. /// <summary>
  45. /// Writer for string types
  46. /// </summary>
  47. function WriteString(const AValue: TValue; ANeonObject: TNeonRttiObject): TJSONValue;
  48. /// <summary>
  49. /// Writer for Char types
  50. /// </summary>
  51. function WriteChar(const AValue: TValue; ANeonObject: TNeonRttiObject): TJSONValue;
  52. /// <summary>
  53. /// Writer for Boolean types
  54. /// </summary>
  55. function WriteBoolean(const AValue: TValue; ANeonObject: TNeonRttiObject): TJSONValue;
  56. /// <summary>
  57. /// Writer for enums types <br />
  58. /// </summary>
  59. function WriteEnum(const AValue: TValue; ANeonObject: TNeonRttiObject): TJSONValue;
  60. /// <summary>
  61. /// Writer for Integer types <br />
  62. /// </summary>
  63. function WriteInteger(const AValue: TValue; ANeonObject: TNeonRttiObject): TJSONValue;
  64. /// <summary>
  65. /// Writer for float types
  66. /// </summary>
  67. function WriteFloat(const AValue: TValue; ANeonObject: TNeonRttiObject): TJSONValue;
  68. /// <summary>
  69. /// Writer for TDate* types
  70. /// </summary>
  71. function WriteDate(const AValue: TValue; ANeonObject: TNeonRttiObject): TJSONValue;
  72. /// <summary>
  73. /// Writer for Variant types
  74. /// </summary>
  75. /// <remarks>
  76. /// The variant will be written as string
  77. /// </remarks>
  78. function WriteVariant(const AValue: TValue; ANeonObject: TNeonRttiObject): TJSONValue;
  79. /// <summary>
  80. /// Writer for static and dynamic arrays
  81. /// </summary>
  82. function WriteArray(const AValue: TValue; ANeonObject: TNeonRttiObject): TJSONValue;
  83. /// <summary>
  84. /// Writer for the set type
  85. /// </summary>
  86. /// <remarks>
  87. /// The output is a string with the values comma separated and enclosed by square brackets
  88. /// </remarks>
  89. /// <returns>[First,Second,Third]</returns>
  90. function WriteSet(const AValue: TValue; ANeonObject: TNeonRttiObject): TJSONValue;
  91. /// <summary>
  92. /// Writer for a record type
  93. /// </summary>
  94. /// <remarks>
  95. /// For records the engine serialize the fields by default
  96. /// </remarks>
  97. function WriteRecord(const AValue: TValue; ANeonObject: TNeonRttiObject): TJSONValue;
  98. /// <summary>
  99. /// Writer for a standard TObject (descendants) type (no list, stream or streamable)
  100. /// </summary>
  101. function WriteObject(const AValue: TValue; ANeonObject: TNeonRttiObject): TJSONValue;
  102. /// <summary>
  103. /// Writer for an Interface type
  104. /// </summary>
  105. /// <remarks>
  106. /// The object that implements the interface is serialized
  107. /// </remarks>
  108. function WriteInterface(const AValue: TValue; ANeonObject: TNeonRttiObject): TJSONValue;
  109. /// <summary>
  110. /// Writer for "Enumerable" objects (Lists, Generic Lists, TStrings, etc...)
  111. /// </summary>
  112. /// <remarks>
  113. /// Objects must have GetEnumerator, Clear, Add methods
  114. /// </remarks>
  115. function WriteEnumerable(const AValue: TValue; ANeonObject: TNeonRttiObject; AList: IDynamicList): TJSONValue;
  116. function IsEnumerable(const AValue: TValue; out AList: IDynamicList): Boolean;
  117. /// <summary>
  118. /// Writer for "Dictionary" objects (TDictionary, TObjectDictionary)
  119. /// </summary>
  120. /// <remarks>
  121. /// Objects must have Keys, Values, GetEnumerator, Clear, Add methods
  122. /// </remarks>
  123. function WriteEnumerableMap(const AValue: TValue; ANeonObject: TNeonRttiObject; AMap: IDynamicMap): TJSONValue;
  124. function IsEnumerableMap(const AValue: TValue; out AMap: IDynamicMap): Boolean;
  125. /// <summary>
  126. /// Writer for "Streamable" objects
  127. /// </summary>
  128. /// <remarks>
  129. /// Objects must have LoadFromStream and SaveToStream methods
  130. /// </remarks>
  131. function WriteStreamable(const AValue: TValue; ANeonObject: TNeonRttiObject; AStream: IDynamicStream): TJSONValue;
  132. function IsStreamable(const AValue: TValue; out AStream: IDynamicStream): Boolean;
  133. /// <summary>
  134. /// Writer for "Nullable" records
  135. /// </summary>
  136. /// <remarks>
  137. /// Record must have HasValue and GetValue methods
  138. /// </remarks>
  139. function WriteNullable(const AValue: TValue; ANeonObject: TNeonRttiObject; ANullable: IDynamicNullable): TJSONValue;
  140. function IsNullable(const AValue: TValue; out ANullable: IDynamicNullable): Boolean;
  141. protected
  142. /// <summary>
  143. /// Function to be called by a custom serializer method (ISerializeContext)
  144. /// </summary>
  145. function WriteDataMember(const AValue: TValue): TJSONValue; overload;
  146. /// <summary>
  147. /// This method chooses the right Writer based on the Kind of the AValue parameter
  148. /// </summary>
  149. function WriteDataMember(const AValue: TValue; ANeonObject: TNeonRttiObject): TJSONValue; overload;
  150. public
  151. constructor Create(const AConfig: INeonConfiguration);
  152. /// <summary>
  153. /// Serialize any Delphi type into a JSONValue, the Delphi type must be passed as a TValue
  154. /// </summary>
  155. function ValueToJSON(const AValue: TValue): TJSONValue;
  156. /// <summary>
  157. /// Serialize any Delphi objects into a JSONValue
  158. /// </summary>
  159. function ObjectToJSON(AObject: TObject): TJSONValue;
  160. end;
  161. TNeonDeserializerParam = record
  162. JSONValue: TJSONValue;
  163. RttiType: TRttiType;
  164. NeonObject: TNeonRttiObject;
  165. procedure Default;
  166. end;
  167. /// <summary>
  168. /// JSON Deserializer class
  169. /// </summary>
  170. TNeonDeserializerJSON = class(TNeonBase, IDeserializerContext)
  171. private
  172. procedure ReadMembers(AType: TRttiType; AInstance: Pointer; AJSONObject: TJSONObject);
  173. private
  174. function ReadString(const AParam: TNeonDeserializerParam): TValue;
  175. function ReadChar(const AParam: TNeonDeserializerParam): TValue;
  176. function ReadEnum(const AParam: TNeonDeserializerParam): TValue;
  177. function ReadInteger(const AParam: TNeonDeserializerParam): TValue;
  178. function ReadInt64(const AParam: TNeonDeserializerParam): TValue;
  179. function ReadFloat(const AParam: TNeonDeserializerParam): TValue;
  180. function ReadSet(const AParam: TNeonDeserializerParam): TValue;
  181. function ReadVariant(const AParam: TNeonDeserializerParam): TValue;
  182. private
  183. function ReadArray(const AParam: TNeonDeserializerParam; const AData: TValue): TValue;
  184. function ReadDynArray(const AParam: TNeonDeserializerParam; const AData: TValue): TValue;
  185. function ReadObject(const AParam: TNeonDeserializerParam; const AData: TValue): TValue;
  186. function ReadInterface(const AParam: TNeonDeserializerParam; const AData: TValue): TValue;
  187. function ReadRecord(const AParam: TNeonDeserializerParam; const AData: TValue): TValue;
  188. // Dynamic types
  189. function ReadStreamable(const AParam: TNeonDeserializerParam; const AData: TValue): Boolean;
  190. function ReadEnumerable(const AParam: TNeonDeserializerParam; const AData: TValue): Boolean;
  191. function ReadEnumerableMap(const AParam: TNeonDeserializerParam; const AData: TValue): Boolean;
  192. function ReadNullable(const AParam: TNeonDeserializerParam; const AData: TValue): Boolean;
  193. private
  194. function ReadDataMember(AJSONValue: TJSONValue; AType: TRttiType; const AData: TValue): TValue; overload;
  195. function ReadDataMember(const AParam: TNeonDeserializerParam; const AData: TValue): TValue; overload;
  196. public
  197. constructor Create(const AConfig: INeonConfiguration);
  198. procedure JSONToObject(AObject: TObject; AJSON: TJSONValue);
  199. function JSONToTValue(AJSON: TJSONValue; AType: TRttiType): TValue; overload;
  200. function JSONToTValue(AJSON: TJSONValue; AType: TRttiType; const AData: TValue): TValue; overload;
  201. function JSONToArray(AJSON: TJSONValue; AType: TRttiType): TValue;
  202. end;
  203. /// <summary>
  204. /// Static utility class for serializing and deserializing Delphi types
  205. /// </summary>
  206. TNeon = class
  207. private
  208. /// <summary>
  209. /// Prints a TJSONValue in a single line or formatted (PrettyPrinting)
  210. /// </summary>
  211. class procedure PrintToWriter(AJSONValue: TJSONValue; AWriter: TTextWriter; APretty: Boolean); static;
  212. public
  213. /// <summary>
  214. /// Prints a TJSONValue in a single line or formatted (PrettyPrinting)
  215. /// </summary>
  216. class function Print(AJSONValue: TJSONValue; APretty: Boolean): string; static;
  217. /// <summary>
  218. /// Prints a TJSONValue in a single line or formatted (PrettyPrinting)
  219. /// </summary>
  220. class procedure PrintToStream(AJSONValue: TJSONValue; AStream: TStream; APretty: Boolean); static;
  221. public
  222. /// <summary>
  223. /// Serializes a value based type (record, string, integer, etc...) to a TStream
  224. /// </summary>
  225. class procedure ValueToStream(const AValue: TValue; AStream: TStream); overload;
  226. /// <summary>
  227. /// Serializes a value based type (record, string, integer, etc...) to a TStream with a given configuration
  228. /// </summary>
  229. class procedure ValueToStream(const AValue: TValue; AStream: TStream; AConfig: INeonConfiguration); overload;
  230. /// <summary>
  231. /// Serializes a value based type (record, string, integer, etc...) to a
  232. /// TJSONValue with a default configuration
  233. /// </summary>
  234. class function ValueToJSON(const AValue: TValue): TJSONValue; overload;
  235. /// <summary>
  236. /// Serializes a value based type (record, string, integer, etc...) to a TJSONValue
  237. /// with a given configuration
  238. /// </summary>
  239. class function ValueToJSON(const AValue: TValue; AConfig: INeonConfiguration): TJSONValue; overload;
  240. public
  241. /// <summary>
  242. /// Serializes an object based type into a TTStream with a default configuration
  243. /// </summary>
  244. class procedure ObjectToStream(AObject: TObject; AStream: TStream); overload;
  245. /// <summary>
  246. /// Serializes an object based type into a TTStream with a given configuration
  247. /// </summary>
  248. class procedure ObjectToStream(AObject: TObject; AStream: TStream; AConfig: INeonConfiguration); overload;
  249. /// <summary>
  250. /// Serializes an object based type to a TJSONValue with a default configuration
  251. /// </summary>
  252. class function ObjectToJSON(AObject: TObject): TJSONValue; overload;
  253. /// <summary>
  254. /// Serializes an object based type to a TJSONValue with a given configuration <br />
  255. /// </summary>
  256. class function ObjectToJSON(AObject: TObject; AConfig: INeonConfiguration): TJSONValue; overload;
  257. /// <summary>
  258. /// Serializes an object based type to a string with a default configuration <br />
  259. /// </summary>
  260. class function ObjectToJSONString(AObject: TObject): string; overload;
  261. /// <summary>
  262. /// Serializes an object based type to a string with a given configuration <br />
  263. /// </summary>
  264. class function ObjectToJSONString(AObject: TObject; AConfig: INeonConfiguration): string; overload;
  265. public
  266. /// <summary>
  267. /// Deserializes a TJSONValue into a TObject with a given configuration
  268. /// </summary>
  269. class procedure JSONToObject(AObject: TObject; AJSON: TJSONValue; AConfig: INeonConfiguration); overload;
  270. /// <summary>
  271. /// Deserializes a string into a TObject with a given configuration
  272. /// </summary>
  273. class procedure JSONToObject(AObject: TObject; const AJSON: string; AConfig: INeonConfiguration); overload;
  274. /// <summary>
  275. /// Deserializes a TJSONValue into a TRttiType with a default configuration
  276. /// </summary>
  277. class function JSONToObject(AType: TRttiType; AJSON: TJSONValue): TObject; overload;
  278. /// <summary>
  279. /// Deserializes a TJSONValue into a TRttiType with a given configuration
  280. /// </summary>
  281. class function JSONToObject(AType: TRttiType; AJSON: TJSONValue; AConfig: INeonConfiguration): TObject; overload;
  282. /// <summary>
  283. /// Deserializes a string into a TRttiType with a default configuration
  284. /// </summary>
  285. class function JSONToObject(AType: TRttiType; const AJSON: string): TObject; overload;
  286. /// <summary>
  287. /// Deserializes a string into a TRttiType with a given configuration
  288. /// </summary>
  289. class function JSONToObject(AType: TRttiType; const AJSON: string; AConfig: INeonConfiguration): TObject; overload;
  290. /// <summary>
  291. /// Deserializes a TJSONValue into a generic type &lt;T&gt; with a default
  292. /// configuration
  293. /// </summary>
  294. class function JSONToObject<T: class, constructor>(AJSON: TJSONValue): T; overload;
  295. /// <summary>
  296. /// Deserializes a TJSONValue into a generic type &lt;T&gt; with a given
  297. /// configuration <br />
  298. /// </summary>
  299. class function JSONToObject<T: class, constructor>(AJSON: TJSONValue; AConfig: INeonConfiguration): T; overload;
  300. /// <summary>
  301. /// Deserializes a string into a generic type &lt;T&gt; with a default
  302. /// configuration <br />
  303. /// </summary>
  304. class function JSONToObject<T: class, constructor>(const AJSON: string): T; overload;
  305. /// <summary>
  306. /// Deserializes a string into a generic type &lt;T&gt; with a given configuration <br />
  307. /// </summary>
  308. class function JSONToObject<T: class, constructor>(const AJSON: string; AConfig: INeonConfiguration): T; overload;
  309. public
  310. /// <summary>
  311. /// Deserializes a TJSONValue into a TRttiType value based with a default
  312. /// configuration <br />
  313. /// </summary>
  314. class function JSONToValue(ARttiType: TRttiType; AJSON: TJSONValue): TValue; overload;
  315. /// <summary>
  316. /// Deserializes a TJSONValue into a TRttiType value based with a given
  317. /// configuration
  318. /// </summary>
  319. class function JSONToValue(ARttiType: TRttiType; AJSON: TJSONValue; AConfig: INeonConfiguration): TValue; overload;
  320. /// <summary>
  321. /// Deserializes a TJSONValue into a generic type &lt;T&gt; (value based) with a
  322. /// default configuration
  323. /// </summary>
  324. class function JSONToValue<T>(AJSON: TJSONValue): T; overload;
  325. /// <summary>
  326. /// Deserializes a TJSONValue into a generic type &lt;T&gt; (value based) with a
  327. /// given configuration <br />
  328. /// </summary>
  329. class function JSONToValue<T>(AJSON: TJSONValue; AConfig: INeonConfiguration): T; overload;
  330. end;
  331. implementation
  332. uses
  333. System.DateUtils,
  334. System.Variants;
  335. { TNeonSerializerJSON }
  336. constructor TNeonSerializerJSON.Create(const AConfig: INeonConfiguration);
  337. begin
  338. inherited Create(AConfig);
  339. FOperation := TNeonOperation.Serialize;
  340. end;
  341. function TNeonSerializerJSON.IsEnumerable(const AValue: TValue; out AList: IDynamicList): Boolean;
  342. begin
  343. AList := TDynamicList.GuessType(AValue.AsObject);
  344. Result := Assigned(AList);
  345. end;
  346. function TNeonSerializerJSON.IsEnumerableMap(const AValue: TValue; out AMap: IDynamicMap): Boolean;
  347. begin
  348. AMap := TDynamicMap.GuessType(AValue.AsObject);
  349. Result := Assigned(AMap);
  350. end;
  351. function TNeonSerializerJSON.IsNullable(const AValue: TValue; out ANullable: IDynamicNullable): Boolean;
  352. begin
  353. ANullable := TDynamicNullable.GuessType(AValue);
  354. Result := Assigned(ANullable);
  355. end;
  356. function TNeonSerializerJSON.IsStreamable(const AValue: TValue; out AStream: IDynamicStream): Boolean;
  357. begin
  358. AStream := TDynamicStream.GuessType(AValue.AsObject);
  359. Result := Assigned(AStream);
  360. end;
  361. function TNeonSerializerJSON.ObjectToJSON(AObject: TObject): TJSONValue;
  362. begin
  363. FOriginalInstance := AObject;
  364. if not Assigned(AObject) then
  365. Exit(TJSONObject.Create);
  366. Result := WriteDataMember(AObject);
  367. end;
  368. function TNeonSerializerJSON.ValueToJSON(const AValue: TValue): TJSONValue;
  369. begin
  370. FOriginalInstance := AValue;
  371. Result := WriteDataMember(AValue);
  372. end;
  373. function TNeonSerializerJSON.WriteArray(const AValue: TValue; ANeonObject: TNeonRttiObject): TJSONValue;
  374. var
  375. LIndex, LCount: Integer;
  376. LArray: TJSONArray;
  377. begin
  378. LCount := AValue.GetArrayLength;
  379. if ANeonObject.NeonInclude.Value = IncludeIf.NotEmpty then
  380. if LCount = 0 then
  381. Exit(nil);
  382. LArray := TJSONArray.Create;
  383. for LIndex := 0 to LCount - 1 do
  384. LArray.AddElement(WriteDataMember(AValue.GetArrayElement(LIndex)));
  385. Result := LArray;
  386. end;
  387. function TNeonSerializerJSON.WriteBoolean(const AValue: TValue; ANeonObject: TNeonRttiObject): TJSONValue;
  388. begin
  389. Result := TJSONBool.Create(AValue.AsBoolean);
  390. end;
  391. function TNeonSerializerJSON.WriteChar(const AValue: TValue; ANeonObject: TNeonRttiObject): TJSONValue;
  392. var
  393. LStr: string;
  394. begin
  395. LStr := AValue.AsString;
  396. case ANeonObject.NeonInclude.Value of
  397. IncludeIf.NotEmpty, IncludeIf.NotDefault:
  398. begin
  399. if (LStr = #0) or LStr.IsEmpty then
  400. Exit(nil);
  401. end;
  402. end;
  403. if (LStr = #0) or LStr.IsEmpty then
  404. Result := TJSONString.Create('')
  405. else
  406. Result := TJSONString.Create(AValue.AsString);
  407. end;
  408. function TNeonSerializerJSON.WriteDataMember(const AValue: TValue): TJSONValue;
  409. var
  410. LNeonObject: TNeonRttiObject;
  411. LRttiType: TRttiType;
  412. begin
  413. LRttiType := TRttiUtils.Context.GetType(AValue.TypeInfo);
  414. LNeonObject := TNeonRttiObject.Create(LRttiType, FOperation);
  415. LNeonObject.ParseAttributes;
  416. try
  417. Result := WriteDataMember(AValue, LNeonObject);
  418. finally
  419. LNeonObject.Free;
  420. end;
  421. end;
  422. function TNeonSerializerJSON.WriteDataMember(const AValue: TValue; ANeonObject: TNeonRttiObject): TJSONValue;
  423. var
  424. LCustomSer: TCustomSerializer;
  425. LDynamicType: IDynamicType;
  426. LDynamicMap: IDynamicMap absolute LDynamicType;
  427. LDynamicList: IDynamicList absolute LDynamicType;
  428. LDynamicStream: IDynamicStream absolute LDynamicType;
  429. LDynamicNullable: IDynamicNullable absolute LDynamicType;
  430. begin
  431. Result := nil;
  432. LCustomSer := FConfig.Serializers.GetSerializer(AValue.TypeInfo);
  433. if Assigned(LCustomSer) then
  434. begin
  435. Result := LCustomSer.Serialize(AValue, ANeonObject, Self);
  436. Exit(Result);
  437. end;
  438. case AValue.Kind of
  439. tkChar,
  440. tkWChar:
  441. begin
  442. Result := WriteChar(AValue, ANeonObject);
  443. end;
  444. tkString,
  445. tkLString,
  446. tkWString,
  447. tkUString:
  448. begin
  449. Result := WriteString(AValue, ANeonObject);
  450. end;
  451. tkEnumeration:
  452. begin
  453. if AValue.TypeInfo = System.TypeInfo(Boolean) then
  454. Result := WriteBoolean(AValue, ANeonObject)
  455. else
  456. Result := WriteEnum(AValue, ANeonObject);
  457. end;
  458. tkInteger,
  459. tkInt64:
  460. begin
  461. Result := WriteInteger(AValue, ANeonObject);
  462. end;
  463. tkFloat:
  464. begin
  465. if (AValue.TypeInfo = System.TypeInfo(TDateTime)) or
  466. (AValue.TypeInfo = System.TypeInfo(TDate)) or
  467. (AValue.TypeInfo = System.TypeInfo(TTime)) then
  468. Result := WriteDate(AValue, ANeonObject)
  469. else
  470. Result := WriteFloat(AValue, ANeonObject);
  471. end;
  472. tkClass:
  473. begin
  474. if AValue.AsObject = nil then
  475. begin
  476. case ANeonObject.NeonInclude.Value of
  477. IncludeIf.Always, IncludeIf.CustomFunction:
  478. Exit(TJSONNull.Create);
  479. else
  480. Exit(nil);
  481. end;
  482. end
  483. else if IsEnumerableMap(AValue, LDynamicMap) then
  484. Result := WriteEnumerableMap(AValue, ANeonObject, LDynamicMap)
  485. else if IsEnumerable(AValue, LDynamicList) then
  486. Result := WriteEnumerable(AValue, ANeonObject, LDynamicList)
  487. else if IsStreamable(AValue, LDynamicStream) then
  488. Result := WriteStreamable(AValue, ANeonObject, LDynamicStream)
  489. else
  490. Result := WriteObject(AValue, ANeonObject);
  491. end;
  492. tkArray:
  493. begin
  494. Result := WriteArray(AValue, ANeonObject);
  495. end;
  496. tkDynArray:
  497. begin
  498. Result := WriteArray(AValue, ANeonObject);
  499. end;
  500. tkSet:
  501. begin
  502. Result := WriteSet(AValue, ANeonObject);
  503. end;
  504. tkRecord{$IFDEF HAS_MRECORDS}, tkMRecord{$ENDIF}:
  505. begin
  506. if IsNullable(AValue, LDynamicNullable) then
  507. Result := WriteNullable(AValue, ANeonObject, LDynamicNullable)
  508. else
  509. Result := WriteRecord(AValue, ANeonObject);
  510. end;
  511. tkInterface:
  512. begin
  513. Result := WriteInterface(AValue, ANeonObject);
  514. end;
  515. tkVariant:
  516. begin
  517. Result := WriteVariant(AValue, ANeonObject);
  518. end;
  519. {
  520. tkUnknown,
  521. tkMethod,
  522. tkPointer,
  523. tkProcedure,
  524. tkClassRef:
  525. }
  526. end;
  527. end;
  528. function TNeonSerializerJSON.WriteDate(const AValue: TValue; ANeonObject: TNeonRttiObject): TJSONValue;
  529. begin
  530. case ANeonObject.NeonInclude.Value of
  531. IncludeIf.NotEmpty, IncludeIf.NotDefault:
  532. begin
  533. if AValue.AsExtended = 0 then
  534. Exit(nil);
  535. end;
  536. end;
  537. Result := TJSONString.Create(TJSONUtils.DateToJSON(AValue.AsType<TDateTime>, FConfig.UseUTCDate))
  538. end;
  539. function TNeonSerializerJSON.WriteEnum(const AValue: TValue; ANeonObject: TNeonRttiObject): TJSONValue;
  540. var
  541. LValue: Int64;
  542. LTypeData: PTypeData;
  543. LName: string;
  544. begin
  545. LName := '';
  546. LValue := AValue.AsOrdinal;
  547. LTypeData := GetTypeData(AValue.TypeInfo);
  548. if (LValue >= LTypeData.MinValue) and (LValue <= LTypeData.MaxValue) then
  549. begin
  550. LName := GetEnumName(AValue.TypeInfo, LValue);
  551. if Length(ANeonObject.NeonEnumNames) > 0 then
  552. begin
  553. if (LValue >= Low(ANeonObject.NeonEnumNames)) and
  554. (LValue <= High(ANeonObject.NeonEnumNames)) then
  555. LName := ANeonObject.NeonEnumNames[LValue]
  556. end;
  557. Result := TJSONString.Create(LName);
  558. end
  559. else
  560. raise ENeonException.Create('Enum value out of bound: ' + LValue.ToString);
  561. end;
  562. function TNeonSerializerJSON.WriteFloat(const AValue: TValue; ANeonObject: TNeonRttiObject): TJSONValue;
  563. begin
  564. case ANeonObject.NeonInclude.Value of
  565. IncludeIf.NotEmpty, IncludeIf.NotDefault:
  566. begin
  567. if AValue.AsExtended = 0 then
  568. Exit(nil);
  569. end;
  570. end;
  571. Result := TJSONNumber.Create(AValue.AsExtended);
  572. end;
  573. function TNeonSerializerJSON.WriteInteger(const AValue: TValue; ANeonObject: TNeonRttiObject): TJSONValue;
  574. begin
  575. case ANeonObject.NeonInclude.Value of
  576. IncludeIf.NotDefault:
  577. begin
  578. if AValue.AsInt64 = 0 then
  579. Exit(nil);
  580. end;
  581. end;
  582. Result := TJSONNumber.Create(AValue.AsInt64);
  583. end;
  584. function TNeonSerializerJSON.WriteInterface(const AValue: TValue; ANeonObject: TNeonRttiObject): TJSONValue;
  585. var
  586. LInterface: IInterface;
  587. LObject: TObject;
  588. begin
  589. LInterface := AValue.AsInterface;
  590. LObject := LInterface as TObject;
  591. Result := WriteObject(LObject, ANeonObject);
  592. end;
  593. procedure TNeonSerializerJSON.WriteMembers(AType: TRttiType; AInstance: Pointer; AResult: TJSONValue);
  594. var
  595. LJSONValue: TJSONValue;
  596. LMembers: TNeonRttiMembers;
  597. LNeonMember: TNeonRttiMember;
  598. begin
  599. LMembers := GetNeonMembers(AInstance, AType);
  600. LMembers.FilterSerialize;
  601. try
  602. for LNeonMember in LMembers do
  603. begin
  604. if LNeonMember.Serializable then
  605. begin
  606. try
  607. LJSONValue := WriteDataMember(LNeonMember.GetValue, LNeonMember);
  608. if Assigned(LJSONValue) then
  609. (AResult as TJSONObject).AddPair(GetNameFromMember(LNeonMember), LJSONValue);
  610. except
  611. on E: Exception do
  612. begin
  613. LogError(Format('Error converting member [%s] of type [%s]: %s',
  614. [LNeonMember.Name, AType.Name, E.Message]));
  615. end;
  616. end;
  617. end;
  618. end;
  619. finally
  620. LMembers.Free;
  621. end;
  622. end;
  623. function TNeonSerializerJSON.WriteNullable(const AValue: TValue; ANeonObject: TNeonRttiObject; ANullable: IDynamicNullable): TJSONValue;
  624. begin
  625. Result := nil;
  626. if not Assigned(ANullable) then
  627. Exit;
  628. case ANeonObject.NeonInclude.Value of
  629. IncludeIf.Always, IncludeIf.CustomFunction:
  630. begin
  631. if ANullable.HasValue then
  632. Result := WriteDataMember(ANullable.GetValue, ANeonObject)
  633. else
  634. Result := TJSONNull.Create;
  635. end;
  636. IncludeIf.NotNull, IncludeIf.NotEmpty, IncludeIf.NotDefault:
  637. begin
  638. if ANullable.HasValue then
  639. Result := WriteDataMember(ANullable.GetValue, ANeonObject);
  640. end;
  641. end;
  642. end;
  643. function TNeonSerializerJSON.WriteObject(const AValue: TValue; ANeonObject: TNeonRttiObject): TJSONValue;
  644. var
  645. LObject: TObject;
  646. LType: TRttiType;
  647. begin
  648. LObject := AValue.AsObject;
  649. if LObject = nil then
  650. Exit(nil);
  651. LType := TRttiUtils.Context.GetType(LObject.ClassType);
  652. Result := TJSONObject.Create;
  653. try
  654. WriteMembers(LType, LObject, Result);
  655. case ANeonObject.NeonInclude.Value of
  656. IncludeIf.NotEmpty, IncludeIf.NotDefault:
  657. begin
  658. if (Result as TJSONObject).Count = 0 then
  659. FreeAndNil(Result);
  660. end;
  661. end;
  662. except
  663. FreeAndNil(Result);
  664. end;
  665. end;
  666. function TNeonSerializerJSON.WriteEnumerable(const AValue: TValue; ANeonObject: TNeonRttiObject; AList: IDynamicList): TJSONValue;
  667. var
  668. LJSONValue: TJSONValue;
  669. begin
  670. // Not an enumerable object
  671. if not Assigned(AList) then
  672. Exit(nil);
  673. if ANeonObject.NeonInclude.Value = IncludeIf.NotEmpty then
  674. if AList.Count = 0 then
  675. Exit(nil);
  676. Result := TJSONArray.Create;
  677. while AList.MoveNext do
  678. begin
  679. LJSONValue := WriteDataMember(AList.Current);
  680. (Result as TJSONArray).AddElement(LJSONValue);
  681. end;
  682. end;
  683. function TNeonSerializerJSON.WriteEnumerableMap(const AValue: TValue; ANeonObject: TNeonRttiObject; AMap: IDynamicMap): TJSONValue;
  684. var
  685. LName: string;
  686. LJSONName: TJSONValue;
  687. LJSONValue: TJSONValue;
  688. LKeyValue, LValValue: TValue;
  689. begin
  690. // Not an EnumerableMap object
  691. if not Assigned(AMap) then
  692. Exit(nil);
  693. case ANeonObject.NeonInclude.Value of
  694. IncludeIf.Always:
  695. begin
  696. if not Assigned(AMap) then
  697. Exit(TJSONNull.Create);
  698. end;
  699. IncludeIf.NotNull:
  700. begin
  701. if not Assigned(AMap) then
  702. Exit(nil);
  703. end;
  704. IncludeIf.NotEmpty:
  705. begin
  706. if AMap.Count = 0 then
  707. Exit(nil);
  708. end;
  709. IncludeIf.NotDefault: ;
  710. end;
  711. Result := TJSONObject.Create;
  712. try
  713. while AMap.MoveNext do
  714. begin
  715. LKeyValue := AMap.CurrentKey;
  716. LValValue := AMap.CurrentValue;
  717. LJSONName := WriteDataMember(LKeyValue);
  718. try
  719. LJSONValue := WriteDataMember(LValValue);
  720. if LJSONName is TJSONString then
  721. LName := (LJSONName as TJSONString).Value
  722. else if AMap.KeyIsString then
  723. LName := AMap.KeyToString(LKeyValue);
  724. (Result as TJSONObject).AddPair(LName, LJSONValue);
  725. if LName.IsEmpty then
  726. raise ENeonException.Create('Dictionary [Key]: type not supported');
  727. finally
  728. LJSONName.Free;
  729. end;
  730. end;
  731. except
  732. on E: Exception do
  733. begin
  734. FErrors.Add(E.Message);
  735. FreeAndNil(Result);
  736. end;
  737. end;
  738. end;
  739. function TNeonSerializerJSON.WriteRecord(const AValue: TValue; ANeonObject: TNeonRttiObject): TJSONValue;
  740. var
  741. LType: TRttiType;
  742. begin
  743. Result := TJSONObject.Create;
  744. LType := TRttiUtils.Context.GetType(AValue.TypeInfo);
  745. try
  746. WriteMembers(LType, AValue.GetReferenceToRawData, Result);
  747. case ANeonObject.NeonInclude.Value of
  748. IncludeIf.NotEmpty, IncludeIf.NotDefault:
  749. begin
  750. if ANeonObject.NeonInclude.Value = IncludeIf.NotEmpty then
  751. if (Result as TJSONObject).Count = 0 then
  752. FreeAndNil(Result);
  753. end;
  754. end;
  755. except
  756. FreeAndNil(Result);
  757. end;
  758. end;
  759. function TNeonSerializerJSON.WriteSet(const AValue: TValue; ANeonObject: TNeonRttiObject): TJSONValue;
  760. var
  761. LRes: string;
  762. begin
  763. LRes := SetToString(AValue.TypeInfo, Integer(AValue.GetReferenceToRawData^), True);
  764. if ANeonObject.NeonInclude.Value = IncludeIf.NotEmpty then
  765. if LRes = '[]' then
  766. Exit(nil);
  767. Result := TJSONString.Create(LRes);
  768. end;
  769. function TNeonSerializerJSON.WriteStreamable(const AValue: TValue; ANeonObject: TNeonRttiObject; AStream: IDynamicStream): TJSONValue;
  770. var
  771. LBinaryStream: TMemoryStream;
  772. LBase64: string;
  773. begin
  774. Result := nil;
  775. if Assigned(AStream) then
  776. begin
  777. LBinaryStream := TMemoryStream.Create;
  778. try
  779. AStream.SaveToStream(LBinaryStream);
  780. LBinaryStream.Position := soFromBeginning;
  781. LBase64 := TBase64.Encode(LBinaryStream);
  782. if IsOriginalInstance(AValue) then
  783. Result := TJSONObject.Create.AddPair('$value', LBase64)
  784. else
  785. Result := TJSONString.Create(LBase64);
  786. finally
  787. LBinaryStream.Free;
  788. end;
  789. end;
  790. end;
  791. function TNeonSerializerJSON.WriteString(const AValue: TValue; ANeonObject: TNeonRttiObject): TJSONValue;
  792. begin
  793. case ANeonObject.NeonInclude.Value of
  794. IncludeIf.NotEmpty, IncludeIf.NotDefault:
  795. begin
  796. if AValue.AsString.IsEmpty then
  797. Exit(nil);
  798. end;
  799. end;
  800. Result := TJSONString.Create(AValue.AsString);
  801. end;
  802. function TNeonSerializerJSON.WriteVariant(const AValue: TValue; ANeonObject: TNeonRttiObject): TJSONValue;
  803. var
  804. LValue: Variant;
  805. LVariantType: Integer;
  806. begin
  807. LValue := AValue.AsVariant;
  808. case ANeonObject.NeonInclude.Value of
  809. IncludeIf.Always:
  810. begin
  811. if VarIsNull(LValue) then
  812. Exit(TJSONNull.Create);
  813. end;
  814. IncludeIf.NotNull:
  815. begin
  816. if VarIsNull(LValue) then
  817. Exit(nil);
  818. end;
  819. IncludeIf.NotEmpty:
  820. begin
  821. if VarIsEmpty(LValue) then
  822. Exit(nil);
  823. end;
  824. end;
  825. LVariantType := VarType(LValue) and VarTypeMask;
  826. case LVariantType of
  827. //varEmpty :
  828. //varNull :
  829. varSmallInt,
  830. varInteger : Result := WriteInteger(Int64(LValue), ANeonObject);
  831. varSingle ,
  832. varDouble ,
  833. varCurrency: Result := WriteFloat(Currency(LValue), ANeonObject);
  834. varDate : Result := WriteDate(VarToDateTime(LValue), ANeonObject);
  835. //varOleStr :
  836. //varDispatch:
  837. //varError :
  838. varBoolean : Result := WriteBoolean(Boolean(LValue), ANeonObject);
  839. //varVariant :
  840. //varUnknown :
  841. varByte ,
  842. varWord ,
  843. varLongWord,
  844. varInt64 : Result := WriteInteger(Int64(LValue), ANeonObject);
  845. //varStrArg :
  846. varString : Result := WriteString(VarToStr(LValue), ANeonObject);
  847. //varAny :
  848. //varTypeMask:
  849. else
  850. Result := TJSONString.Create(AValue.AsVariant);
  851. end;
  852. end;
  853. { TNeonDeserializerJSON }
  854. constructor TNeonDeserializerJSON.Create(const AConfig: INeonConfiguration);
  855. begin
  856. inherited Create(AConfig);
  857. FOperation := TNeonOperation.Deserialize;
  858. end;
  859. function TNeonDeserializerJSON.ReadArray(const AParam: TNeonDeserializerParam; const AData: TValue): TValue;
  860. var
  861. LIndex: NativeInt;
  862. LItemValue: TValue;
  863. LJSONArray: TJSONArray;
  864. LParam: TNeonDeserializerParam;
  865. begin
  866. // TValue record copy (but the TValue only copy the reference to Data)
  867. Result := AData;
  868. LParam.NeonObject := AParam.NeonObject;
  869. // Clear (and Free) previous elements?
  870. LJSONArray := AParam.JSONValue as TJSONArray;
  871. LParam.RttiType := (AParam.RttiType as TRttiArrayType).ElementType;
  872. // Check static array bounds
  873. for LIndex := 0 to LJSONArray.Count - 1 do
  874. begin
  875. LParam.JSONValue := LJSONArray.Items[LIndex];
  876. LItemValue := TRttiUtils.CreateNewValue(LParam.RttiType);
  877. LItemValue := ReadDataMember(LParam, Result);
  878. Result.SetArrayElement(LIndex, LItemValue);
  879. end;
  880. end;
  881. function TNeonDeserializerJSON.ReadDynArray(const AParam: TNeonDeserializerParam; const AData: TValue): TValue;
  882. var
  883. LIndex: NativeInt;
  884. LItemValue: TValue;
  885. LArrayLength: NativeInt;
  886. LJSONArray: TJSONArray;
  887. LParam: TNeonDeserializerParam;
  888. begin
  889. Result := AData;
  890. LParam.NeonObject := AParam.NeonObject;
  891. // Clear (and Free) previous elements?
  892. LJSONArray := AParam.JSONValue as TJSONArray;
  893. LParam.RttiType := (AParam.RttiType as TRttiDynamicArrayType).ElementType;
  894. LArrayLength := LJSONArray.Count;
  895. DynArraySetLength(PPointer(Result.GetReferenceToRawData)^, Result.TypeInfo, 1, @LArrayLength);
  896. for LIndex := 0 to LJSONArray.Count - 1 do
  897. begin
  898. LParam.JSONValue := LJSONArray.Items[LIndex];
  899. LItemValue := TRttiUtils.CreateNewValue(LParam.RttiType);
  900. LItemValue := ReadDataMember(LParam, LItemValue);
  901. Result.SetArrayElement(LIndex, LItemValue);
  902. end;
  903. end;
  904. function TNeonDeserializerJSON.ReadChar(const AParam: TNeonDeserializerParam): TValue;
  905. begin
  906. if (AParam.JSONValue is TJSONNull) or AParam.JSONValue.Value.IsEmpty then
  907. Exit(#0);
  908. case AParam.RttiType.TypeKind of
  909. // AnsiChar
  910. tkChar: Result := TValue.From<UTF8Char>(UTF8Char(AParam.JSONValue.Value.Chars[0]));
  911. // WideChar
  912. tkWChar: Result := TValue.From<Char>(AParam.JSONValue.Value.Chars[0]);
  913. end;
  914. end;
  915. function TNeonDeserializerJSON.ReadDataMember(AJSONValue: TJSONValue; AType: TRttiType; const AData: TValue): TValue;
  916. var
  917. LParam: TNeonDeserializerParam;
  918. begin
  919. LParam.JSONValue := AJSONValue;
  920. LParam.RttiType := AType;
  921. LParam.NeonObject := TNeonRttiObject.Create(AType, FOperation);
  922. LParam.NeonObject.ParseAttributes;
  923. try
  924. Result := ReadDataMember(LParam, AData);
  925. finally
  926. LParam.NeonObject.Free;
  927. end;
  928. end;
  929. function TNeonDeserializerJSON.ReadDataMember(const AParam: TNeonDeserializerParam; const AData: TValue): TValue;
  930. var
  931. LCustom: TCustomSerializer;
  932. begin
  933. if AParam.JSONValue is TJSONNull then
  934. Exit(TValue.Empty);
  935. // if there is a custom serializer
  936. LCustom := FConfig.Serializers.GetSerializer(AParam.RttiType.Handle);
  937. if Assigned(LCustom) then
  938. begin
  939. Result := LCustom.Deserialize(AParam.JSONValue, AData, AParam.NeonObject, Self);
  940. Exit(Result);
  941. end;
  942. case AParam.RttiType.TypeKind of
  943. // Simple types
  944. tkInt64: Result := ReadInt64(AParam);
  945. tkInteger: Result := ReadInteger(AParam);
  946. tkChar: Result := ReadChar(AParam);
  947. tkWChar: Result := ReadChar(AParam);
  948. tkEnumeration: Result := ReadEnum(AParam);
  949. tkFloat: Result := ReadFloat(AParam);
  950. tkLString: Result := ReadString(AParam);
  951. tkWString: Result := ReadString(AParam);
  952. tkUString: Result := ReadString(AParam);
  953. tkString: Result := ReadString(AParam);
  954. tkSet: Result := ReadSet(AParam);
  955. tkVariant: Result := ReadVariant(AParam);
  956. tkArray: Result := ReadArray(AParam, AData);
  957. tkDynArray: Result := ReadDynArray(AParam, AData);
  958. // Complex types
  959. tkClass:
  960. begin
  961. if ReadEnumerableMap(AParam, AData) then
  962. Result := AData
  963. else if ReadEnumerable(AParam, AData) then
  964. Result := AData
  965. else if ReadStreamable(AParam, AData) then
  966. Result := AData
  967. else
  968. Result := ReadObject(AParam, AData);
  969. end;
  970. tkInterface: Result := ReadInterface(AParam, AData);
  971. tkRecord{$IFDEF HAS_MRECORDS}, tkMRecord{$ENDIF}:
  972. begin
  973. if ReadNullable(AParam, AData) then
  974. Result := AData
  975. else
  976. Result := ReadRecord(AParam, AData);
  977. end;
  978. // Not supported (yet)
  979. {
  980. tkUnknown: ;
  981. tkClassRef: ;
  982. tkPointer: ;
  983. tkMethod: ;
  984. tkProcedure: ;
  985. }
  986. else Result := TValue.Empty;
  987. end;
  988. end;
  989. function TNeonDeserializerJSON.ReadEnum(const AParam: TNeonDeserializerParam): TValue;
  990. var
  991. LIndex, LOrdinal: Integer;
  992. LTypeData: PTypeData;
  993. begin
  994. if AParam.RttiType.Handle = System.TypeInfo(Boolean) then
  995. begin
  996. if AParam.JSONValue is TJSONTrue then
  997. Result := True
  998. else if AParam.JSONValue is TJSONFalse then
  999. Result := False
  1000. else
  1001. raise ENeonException.Create('Invalid JSON value. Boolean expected');
  1002. end
  1003. else
  1004. begin
  1005. LOrdinal := -1;
  1006. if Length(AParam.NeonObject.NeonEnumNames) > 0 then
  1007. begin
  1008. for LIndex := Low(AParam.NeonObject.NeonEnumNames) to High(AParam.NeonObject.NeonEnumNames) do
  1009. if AParam.JSONValue.Value = AParam.NeonObject.NeonEnumNames[LIndex] then
  1010. LOrdinal := LIndex;
  1011. end;
  1012. if LOrdinal = -1 then
  1013. LOrdinal := GetEnumValue(AParam.RttiType.Handle, AParam.JSONValue.Value);
  1014. LTypeData := GetTypeData(AParam.RttiType.Handle);
  1015. if (LOrdinal >= LTypeData.MinValue) and (LOrdinal <= LTypeData.MaxValue) then
  1016. TValue.Make(LOrdinal, AParam.RttiType.Handle, Result)
  1017. else
  1018. raise ENeonException.Create('No correspondence with enum names');
  1019. end;
  1020. end;
  1021. function TNeonDeserializerJSON.ReadEnumerable(const AParam: TNeonDeserializerParam; const AData: TValue): Boolean;
  1022. var
  1023. LItemValue: TValue;
  1024. LList: IDynamicList;
  1025. LJSONArray: TJSONArray;
  1026. LIndex: Integer;
  1027. LParam: TNeonDeserializerParam;
  1028. begin
  1029. Result := False;
  1030. LParam.NeonObject := AParam.NeonObject;
  1031. LList := TDynamicList.GuessType(AData.AsObject);
  1032. if Assigned(LList) then
  1033. begin
  1034. Result := True;
  1035. LParam.RttiType := LList.GetItemType;
  1036. LList.Clear;
  1037. LJSONArray := AParam.JSONValue as TJSONArray;
  1038. for LIndex := 0 to LJSONArray.Count - 1 do
  1039. begin
  1040. LParam.JSONValue := LJSONArray.Items[LIndex];
  1041. LItemValue := LList.NewItem;
  1042. LItemValue := ReadDataMember(LParam, LItemValue);
  1043. LList.Add(LItemValue);
  1044. end;
  1045. end;
  1046. end;
  1047. function TNeonDeserializerJSON.ReadEnumerableMap(const AParam: TNeonDeserializerParam; const AData: TValue): Boolean;
  1048. var
  1049. LMap: IDynamicMap;
  1050. {$IFDEF HAS_NEW_JSON}
  1051. LEnum: TJSONObject.TEnumerator;
  1052. {$ELSE}
  1053. LEnum: TJSONPairEnumerator;
  1054. {$ENDIF}
  1055. LKey, LValue: TValue;
  1056. LParamKey, LParamValue: TNeonDeserializerParam;
  1057. begin
  1058. Result := False;
  1059. LParamKey.NeonObject := AParam.NeonObject;
  1060. LParamValue.NeonObject := AParam.NeonObject;
  1061. LMap := TDynamicMap.GuessType(AData.AsObject);
  1062. if Assigned(LMap) then
  1063. begin
  1064. Result := True;
  1065. LParamKey.RttiType := LMap.GetKeyType;
  1066. LParamValue.RttiType := LMap.GetValueType;
  1067. LMap.Clear;
  1068. LEnum := (AParam.JSONValue as TJSONObject).GetEnumerator;
  1069. try
  1070. while LEnum.MoveNext do
  1071. begin
  1072. LKey := LMap.NewKey;
  1073. LParamKey.JSONValue := LEnum.Current.JsonString;
  1074. if LParamKey.RttiType.TypeKind = tkClass then
  1075. LMap.KeyFromString(LKey, LEnum.Current.JsonString.Value)
  1076. else
  1077. LKey := ReadDataMember(LParamKey, LKey);
  1078. LValue := LMap.NewValue;
  1079. LParamValue.JSONValue := LEnum.Current.JsonValue;
  1080. LValue := ReadDataMember(LParamValue, LValue);
  1081. LMap.Add(LKey, LValue);
  1082. end;
  1083. finally
  1084. LEnum.Free;
  1085. end;
  1086. end;
  1087. end;
  1088. function TNeonDeserializerJSON.ReadFloat(const AParam: TNeonDeserializerParam): TValue;
  1089. begin
  1090. if AParam.JSONValue is TJSONNull then
  1091. Exit(0);
  1092. if AParam.RttiType.Handle = System.TypeInfo(TDate) then
  1093. Result := TValue.From<TDate>(TJSONUtils.JSONToDate(AParam.JSONValue.Value, True))
  1094. else if AParam.RttiType.Handle = System.TypeInfo(TTime) then
  1095. Result := TValue.From<TTime>(TJSONUtils.JSONToDate(AParam.JSONValue.Value, True))
  1096. else if AParam.RttiType.Handle = System.TypeInfo(TDateTime) then
  1097. Result := TValue.From<TDateTime>(TJSONUtils.JSONToDate(AParam.JSONValue.Value, FConfig.UseUTCDate))
  1098. else
  1099. begin
  1100. if AParam.JSONValue is TJSONNumber then
  1101. Result := (AParam.JSONValue as TJSONNumber).AsDouble
  1102. else
  1103. raise ENeonException.Create('Invalid JSON value. Float expected');
  1104. end;
  1105. end;
  1106. function TNeonDeserializerJSON.ReadInt64(const AParam: TNeonDeserializerParam): TValue;
  1107. var
  1108. LNumber: TJSONNumber;
  1109. begin
  1110. if AParam.JSONValue is TJSONNull then
  1111. Exit(0);
  1112. LNumber := AParam.JSONValue as TJSONNumber;
  1113. Result := LNumber.AsInt64
  1114. end;
  1115. function TNeonDeserializerJSON.ReadInteger(const AParam: TNeonDeserializerParam): TValue;
  1116. var
  1117. LNumber: TJSONNumber;
  1118. begin
  1119. if AParam.JSONValue is TJSONNull then
  1120. Exit(0);
  1121. LNumber := AParam.JSONValue as TJSONNumber;
  1122. Result := LNumber.AsInt;
  1123. end;
  1124. function TNeonDeserializerJSON.ReadInterface(const AParam: TNeonDeserializerParam; const AData: TValue): TValue;
  1125. begin
  1126. Result := AData;
  1127. end;
  1128. procedure TNeonDeserializerJSON.ReadMembers(AType: TRttiType; AInstance: Pointer; AJSONObject: TJSONObject);
  1129. var
  1130. LMembers: TNeonRttiMembers;
  1131. LNeonMember: TNeonRttiMember;
  1132. LMemberValue: TValue;
  1133. LParam: TNeonDeserializerParam;
  1134. begin
  1135. LMembers := GetNeonMembers(AInstance, AType);
  1136. LMembers.FilterDeserialize;
  1137. try
  1138. for LNeonMember in LMembers do
  1139. begin
  1140. if LNeonMember.Serializable then
  1141. begin
  1142. LParam.NeonObject := LNeonMember;
  1143. LParam.RttiType := LNeonMember.RttiType;
  1144. //Look for a JSON with the calculated Member Name
  1145. LParam.JSONValue := AJSONObject.GetValue(GetNameFromMember(LNeonMember));
  1146. // Property not found in JSON, continue to the next one
  1147. if not Assigned(LParam.JSONValue) then
  1148. Continue;
  1149. try
  1150. LMemberValue := ReadDataMember(LParam, LNeonMember.GetValue);
  1151. LNeonMember.SetValue(LMemberValue);
  1152. except
  1153. on E: Exception do
  1154. begin
  1155. LogError(Format('Error converting member [%s] of type [%s]: %s',
  1156. [LNeonMember.Name, AType.Name, E.Message]));
  1157. end;
  1158. end;
  1159. end;
  1160. end;
  1161. finally
  1162. LMembers.Free;
  1163. end;
  1164. end;
  1165. function TNeonDeserializerJSON.ReadNullable(const AParam: TNeonDeserializerParam; const AData: TValue): Boolean;
  1166. var
  1167. LNullable: IDynamicNullable;
  1168. LValue: TValue;
  1169. LValueType: TRttiType;
  1170. begin
  1171. Result := False;
  1172. LNullable := TDynamicNullable.GuessType(AData);
  1173. if Assigned(LNullable) then
  1174. begin
  1175. Result := True;
  1176. LValueType := TRttiUtils.Context.GetType(LNullable.GetValueType);
  1177. LValue := JSONToTValue(AParam.JSONValue, LValueType);
  1178. LNullable.SetValue(LValue);
  1179. end;
  1180. end;
  1181. function TNeonDeserializerJSON.ReadObject(const AParam: TNeonDeserializerParam; const AData: TValue): TValue;
  1182. var
  1183. LJSONObject: TJSONObject;
  1184. LPData: Pointer;
  1185. begin
  1186. Result := AData;
  1187. LPData := AData.AsObject;
  1188. if not Assigned(LPData) then
  1189. Exit;
  1190. LJSONObject := AParam.JSONValue as TJSONObject;
  1191. if (AParam.RttiType.TypeKind = tkClass) or (AParam.RttiType.TypeKind = tkInterface) then
  1192. ReadMembers(AParam.RttiType, LPData, LJSONObject);
  1193. end;
  1194. function TNeonDeserializerJSON.ReadRecord(const AParam: TNeonDeserializerParam; const AData: TValue): TValue;
  1195. var
  1196. LJSONObject: TJSONObject;
  1197. LPData: Pointer;
  1198. begin
  1199. Result := AData;
  1200. LPData := AData.GetReferenceToRawData;
  1201. if not Assigned(LPData) then
  1202. Exit;
  1203. // Objects, Records, Interfaces are all represented by JSON objects
  1204. LJSONObject := AParam.JSONValue as TJSONObject;
  1205. ReadMembers(AParam.RttiType, LPData, LJSONObject);
  1206. end;
  1207. function TNeonDeserializerJSON.ReadSet(const AParam: TNeonDeserializerParam): TValue;
  1208. var
  1209. LSetStr: string;
  1210. begin
  1211. LSetStr := AParam.JSONValue.Value;
  1212. LSetStr := LSetStr.Replace(sLineBreak, '', [rfReplaceAll]);
  1213. LSetStr := LSetStr.Replace(' ', '', [rfReplaceAll]);
  1214. TValue.Make(StringToSet(AParam.RttiType.Handle, LSetStr), AParam.RttiType.Handle, Result);
  1215. end;
  1216. function TNeonDeserializerJSON.ReadStreamable(const AParam: TNeonDeserializerParam; const AData: TValue): Boolean;
  1217. var
  1218. LStream: TMemoryStream;
  1219. LStreamable: IDynamicStream;
  1220. LJSONValue: TJSONValue;
  1221. begin
  1222. Result := False;
  1223. LStreamable := TDynamicStream.GuessType(AData.AsObject);
  1224. if Assigned(LStreamable) then
  1225. begin
  1226. Result := True;
  1227. LStream := TMemoryStream.Create;
  1228. try
  1229. if IsOriginalInstance(AData) then
  1230. LJSONValue := (AParam.JSONValue as TJSONObject).GetValue('$value')
  1231. else
  1232. LJSONValue := AParam.JSONValue;
  1233. TBase64.Decode(LJSONValue.Value, LStream);
  1234. LStream.Position := soFromBeginning;
  1235. LStreamable.LoadFromStream(LStream);
  1236. finally
  1237. LStream.Free;
  1238. end;
  1239. end;
  1240. end;
  1241. function TNeonDeserializerJSON.ReadString(const AParam: TNeonDeserializerParam): TValue;
  1242. begin
  1243. case AParam.RttiType.TypeKind of
  1244. // AnsiString
  1245. tkLString: Result := TValue.From<UTF8String>(UTF8String(AParam.JSONValue.Value));
  1246. //WideString
  1247. tkWString: Result := TValue.From<WideString>(AParam.JSONValue.Value);
  1248. //UnicodeString
  1249. tkUString: Result := TValue.From<string>(AParam.JSONValue.Value);
  1250. //ShortString
  1251. tkString: Result := TValue.From<UTF8String>(UTF8String(AParam.JSONValue.Value));
  1252. // Future string types treated as unicode strings
  1253. else
  1254. Result := AParam.JSONValue.Value;
  1255. end;
  1256. end;
  1257. function TNeonDeserializerJSON.ReadVariant(const AParam: TNeonDeserializerParam): TValue;
  1258. var
  1259. LDateTime: TDateTime;
  1260. LJSONNumber: TJSONNumber;
  1261. LJSONString: TJSONString;
  1262. begin
  1263. if AParam.JSONValue is TJSONNull then
  1264. Result := TValue.FromVariant(Null)
  1265. else if AParam.JSONValue is TJSONTrue then
  1266. Result := TValue.FromVariant(True)
  1267. else if AParam.JSONValue is TJSONFalse then
  1268. Result := TValue.FromVariant(False)
  1269. else if AParam.JSONValue is TJSONNumber then
  1270. begin
  1271. LJSONNumber := AParam.JSONValue as TJSONNumber;
  1272. Result := TValue.FromVariant(LJSONNumber.AsDouble);
  1273. end
  1274. else if AParam.JSONValue is TJSONString then
  1275. begin
  1276. LJSONString := AParam.JSONValue as TJSONString;
  1277. try
  1278. LDateTime := ISO8601ToDate(LJSONString.Value, FConfig.UseUTCDate);
  1279. Result := TValue.FromVariant(VarFromDateTime(LDateTime))
  1280. except
  1281. Result := TValue.FromVariant(LJSONString.Value);
  1282. end;
  1283. end;
  1284. end;
  1285. function TNeonDeserializerJSON.JSONToArray(AJSON: TJSONValue; AType: TRttiType): TValue;
  1286. begin
  1287. Result := ReadDataMember(AJSON, AType, TValue.Empty);
  1288. end;
  1289. procedure TNeonDeserializerJSON.JSONToObject(AObject: TObject; AJSON: TJSONValue);
  1290. var
  1291. LType: TRttiType;
  1292. LValue: TValue;
  1293. begin
  1294. FOriginalInstance := AObject;
  1295. LType := TRttiUtils.Context.GetType(AObject.ClassType);
  1296. LValue := AObject;
  1297. ReadDataMember(AJSON, LType, AObject);
  1298. end;
  1299. function TNeonDeserializerJSON.JSONToTValue(AJSON: TJSONValue; AType: TRttiType; const AData: TValue): TValue;
  1300. begin
  1301. FOriginalInstance := AData;
  1302. Result := ReadDataMember(AJSON, AType, AData);
  1303. end;
  1304. function TNeonDeserializerJSON.JSONToTValue(AJSON: TJSONValue; AType: TRttiType): TValue;
  1305. begin
  1306. //FOriginalInstance := TValue.Empty;
  1307. Result := ReadDataMember(AJSON, AType, TValue.Empty);
  1308. end;
  1309. { TNeon }
  1310. class function TNeon.JSONToObject(AType: TRttiType; AJSON: TJSONValue): TObject;
  1311. begin
  1312. Result := JSONToObject(AType, AJSON, TNeonConfiguration.Default);
  1313. end;
  1314. class function TNeon.JSONToObject(AType: TRttiType; const AJSON: string): TObject;
  1315. begin
  1316. Result := JSONToObject(AType, AJSON, TNeonConfiguration.Default);
  1317. end;
  1318. class function TNeon.JSONToObject(AType: TRttiType; AJSON: TJSONValue; AConfig: INeonConfiguration): TObject;
  1319. begin
  1320. Result := TRttiUtils.CreateInstance(AType);
  1321. JSONToObject(Result, AJSON, AConfig);
  1322. end;
  1323. class function TNeon.JSONToObject<T>(AJSON: TJSONValue): T;
  1324. begin
  1325. Result := JSONToObject(TRttiUtils.Context.GetType(TClass(T)), AJSON) as T;
  1326. end;
  1327. class procedure TNeon.JSONToObject(AObject: TObject; const AJSON: string; AConfig: INeonConfiguration);
  1328. var
  1329. LJSON: TJSONValue;
  1330. begin
  1331. LJSON := TJSONObject.ParseJSONValue(AJSON);
  1332. try
  1333. JSONToObject(AObject, LJSON, AConfig);
  1334. finally
  1335. LJSON.Free;
  1336. end;
  1337. end;
  1338. class function TNeon.JSONToObject<T>(const AJSON: string): T;
  1339. begin
  1340. Result := JSONToObject(TRttiUtils.Context.GetType(TClass(T)), AJSON) as T;
  1341. end;
  1342. class function TNeon.ObjectToJSON(AObject: TObject; AConfig: INeonConfiguration): TJSONValue;
  1343. var
  1344. LWriter: TNeonSerializerJSON;
  1345. begin
  1346. LWriter := TNeonSerializerJSON.Create(AConfig);
  1347. try
  1348. Result := LWriter.ObjectToJSON(AObject);
  1349. finally
  1350. LWriter.Free;
  1351. end;
  1352. end;
  1353. class function TNeon.ObjectToJSONString(AObject: TObject): string;
  1354. begin
  1355. Result := TNeon.ObjectToJSONString(AObject, TNeonConfiguration.Default);
  1356. end;
  1357. class function TNeon.ObjectToJSON(AObject: TObject): TJSONValue;
  1358. begin
  1359. Result := TNeon.ObjectToJSON(AObject, TNeonConfiguration.Default);
  1360. end;
  1361. class function TNeon.ObjectToJSONString(AObject: TObject; AConfig: INeonConfiguration): string;
  1362. var
  1363. LJSON: TJSONValue;
  1364. begin
  1365. LJSON := ObjectToJSON(AObject, AConfig);
  1366. try
  1367. Result := Print(LJSON, AConfig.GetPrettyPrint);
  1368. finally
  1369. LJSON.Free;
  1370. end;
  1371. end;
  1372. class procedure TNeon.ObjectToStream(AObject: TObject; AStream: TStream);
  1373. begin
  1374. ObjectToStream(AObject, AStream, TNeonConfiguration.Default);
  1375. end;
  1376. class procedure TNeon.ObjectToStream(AObject: TObject; AStream: TStream; AConfig: INeonConfiguration);
  1377. var
  1378. LJSON: TJSONValue;
  1379. begin
  1380. LJSON := TNeon.ObjectToJSON(AObject, AConfig);
  1381. try
  1382. PrintToStream(LJSON, AStream, AConfig.GetPrettyPrint);
  1383. finally
  1384. LJSON.Free;
  1385. end;
  1386. end;
  1387. class function TNeon.Print(AJSONValue: TJSONValue; APretty: Boolean): string;
  1388. var
  1389. LWriter: TStringWriter;
  1390. begin
  1391. LWriter := TStringWriter.Create;
  1392. try
  1393. TNeon.PrintToWriter(AJSONValue, LWriter, APretty);
  1394. Result := LWriter.ToString;
  1395. finally
  1396. LWriter.Free;
  1397. end;
  1398. end;
  1399. class procedure TNeon.PrintToStream(AJSONValue: TJSONValue; AStream: TStream; APretty: Boolean);
  1400. var
  1401. LWriter: TStreamWriter;
  1402. begin
  1403. LWriter := TStreamWriter.Create(AStream);
  1404. try
  1405. TNeon.PrintToWriter(AJSONValue, LWriter, APretty);
  1406. finally
  1407. LWriter.Free;
  1408. end;
  1409. end;
  1410. class procedure TNeon.PrintToWriter(AJSONValue: TJSONValue; AWriter: TTextWriter; APretty: Boolean);
  1411. var
  1412. LJSONString: string;
  1413. LChar: Char;
  1414. LOffset: Integer;
  1415. LIndex: Integer;
  1416. LOutsideString: Boolean;
  1417. function Spaces(AOffset: Integer): string;
  1418. begin
  1419. Result := StringOfChar(#32, AOffset * 2);
  1420. end;
  1421. begin
  1422. if not APretty then
  1423. begin
  1424. AWriter.Write(AJSONValue.ToJSON);
  1425. Exit;
  1426. end;
  1427. LOffset := 0;
  1428. LOutsideString := True;
  1429. LJSONString := AJSONValue.ToJSON;
  1430. for LIndex := 0 to Length(LJSONString) - 1 do
  1431. begin
  1432. LChar := LJSONString.Chars[LIndex];
  1433. if LChar = '"' then
  1434. LOutsideString := not LOutsideString;
  1435. if LOutsideString and (LChar = '{') then
  1436. begin
  1437. Inc(LOffset);
  1438. AWriter.Write(LChar);
  1439. AWriter.Write(sLineBreak);
  1440. AWriter.Write(Spaces(LOffset));
  1441. end
  1442. else if LOutsideString and (LChar = '}') then
  1443. begin
  1444. Dec(LOffset);
  1445. AWriter.Write(sLineBreak);
  1446. AWriter.Write(Spaces(LOffset));
  1447. AWriter.Write(LChar);
  1448. end
  1449. else if LOutsideString and (LChar = ',') then
  1450. begin
  1451. AWriter.Write(LChar);
  1452. AWriter.Write(sLineBreak);
  1453. AWriter.Write(Spaces(LOffset));
  1454. end
  1455. else if LOutsideString and (LChar = '[') then
  1456. begin
  1457. Inc(LOffset);
  1458. AWriter.Write(LChar);
  1459. AWriter.Write(sLineBreak);
  1460. AWriter.Write(Spaces(LOffset));
  1461. end
  1462. else if LOutsideString and (LChar = ']') then
  1463. begin
  1464. Dec(LOffset);
  1465. AWriter.Write(sLineBreak);
  1466. AWriter.Write(Spaces(LOffset));
  1467. AWriter.Write(LChar);
  1468. end
  1469. else if LOutsideString and (LChar = ':') then
  1470. begin
  1471. AWriter.Write(LChar);
  1472. AWriter.Write(' ');
  1473. end
  1474. else
  1475. AWriter.Write(LChar);
  1476. end;
  1477. end;
  1478. class function TNeon.ValueToJSON(const AValue: TValue): TJSONValue;
  1479. begin
  1480. Result := TNeon.ValueToJSON(AValue, TNeonConfiguration.Default);
  1481. end;
  1482. class function TNeon.ValueToJSON(const AValue: TValue; AConfig: INeonConfiguration): TJSONValue;
  1483. var
  1484. LWriter: TNeonSerializerJSON;
  1485. begin
  1486. LWriter := TNeonSerializerJSON.Create(AConfig);
  1487. try
  1488. Result := LWriter.ValueToJSON(AValue);
  1489. finally
  1490. LWriter.Free;
  1491. end;
  1492. end;
  1493. class procedure TNeon.ValueToStream(const AValue: TValue; AStream: TStream);
  1494. begin
  1495. ValueToStream(AValue, AStream, TNeonConfiguration.Default);
  1496. end;
  1497. class procedure TNeon.ValueToStream(const AValue: TValue; AStream: TStream; AConfig: INeonConfiguration);
  1498. var
  1499. LJSON: TJSONValue;
  1500. begin
  1501. LJSON := TNeon.ValueToJSON(AValue, AConfig);
  1502. try
  1503. PrintToStream(LJSON, AStream, AConfig.GetPrettyPrint);
  1504. finally
  1505. LJSON.Free;
  1506. end;
  1507. end;
  1508. class procedure TNeon.JSONToObject(AObject: TObject; AJSON: TJSONValue; AConfig: INeonConfiguration);
  1509. var
  1510. LReader: TNeonDeserializerJSON;
  1511. begin
  1512. LReader := TNeonDeserializerJSON.Create(AConfig);
  1513. try
  1514. LReader.JSONToObject(AObject, AJSON);
  1515. finally
  1516. LReader.Free;
  1517. end;
  1518. end;
  1519. class function TNeon.JSONToObject(AType: TRttiType; const AJSON: string; AConfig: INeonConfiguration): TObject;
  1520. var
  1521. LJSON: TJSONValue;
  1522. begin
  1523. LJSON := TJSONObject.ParseJSONValue(AJSON);
  1524. try
  1525. Result := TRttiUtils.CreateInstance(AType);
  1526. JSONToObject(Result, LJSON, AConfig);
  1527. finally
  1528. LJSON.Free;
  1529. end;
  1530. end;
  1531. class function TNeon.JSONToObject<T>(AJSON: TJSONValue; AConfig: INeonConfiguration): T;
  1532. begin
  1533. Result := JSONToObject(TRttiUtils.Context.GetType(TClass(T)), AJSON, AConfig) as T;
  1534. end;
  1535. class function TNeon.JSONToObject<T>(const AJSON: string; AConfig: INeonConfiguration): T;
  1536. begin
  1537. Result := JSONToObject(TRttiUtils.Context.GetType(TClass(T)), AJSON, AConfig) as T;
  1538. end;
  1539. class function TNeon.JSONToValue(ARttiType: TRttiType; AJSON: TJSONValue;
  1540. AConfig: INeonConfiguration): TValue;
  1541. var
  1542. LDes: TNeonDeserializerJSON;
  1543. begin
  1544. LDes := TNeonDeserializerJSON.Create(AConfig);
  1545. try
  1546. Result := LDes.JSONToTValue(AJSON, ARttiType);
  1547. finally
  1548. LDes.Free;
  1549. end;
  1550. end;
  1551. class function TNeon.JSONToValue(ARttiType: TRttiType; AJSON: TJSONValue): TValue;
  1552. begin
  1553. Result := JSONToValue(ARttiType, AJSON, TNeonConfiguration.Default);
  1554. end;
  1555. class function TNeon.JSONToValue<T>(AJSON: TJSONValue; AConfig: INeonConfiguration): T;
  1556. var
  1557. LDes: TNeonDeserializerJSON;
  1558. LValue: TValue;
  1559. LType: TRttiType;
  1560. begin
  1561. LDes := TNeonDeserializerJSON.Create(AConfig);
  1562. try
  1563. LType := TRttiUtils.Context.GetType(TypeInfo(T));
  1564. if not Assigned(LType) then
  1565. raise ENeonException.Create('Empty RttiType in JSONToValue');
  1566. case LType.TypeKind of
  1567. tkArray, tkRecord, tkDynArray: TValue.Make(nil, TypeInfo(T), LValue);
  1568. else
  1569. LValue := TValue.Empty;
  1570. end;
  1571. LValue := LDes.JSONToTValue(AJSON, LType, LValue);
  1572. Result := LValue.AsType<T>;
  1573. finally
  1574. LDes.Free;
  1575. end;
  1576. end;
  1577. class function TNeon.JSONToValue<T>(AJSON: TJSONValue): T;
  1578. begin
  1579. Result := JSONToValue<T>(AJSON, TNeonConfiguration.Default);
  1580. end;
  1581. { TNeonDeserializerParam }
  1582. procedure TNeonDeserializerParam.Default;
  1583. begin
  1584. JSONValue := nil;
  1585. RttiType := nil;
  1586. NeonObject := nil;
  1587. end;
  1588. end.