testjsonparser.pas 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869
  1. {
  2. This file is part of the Free Component Library
  3. JSON FPCUNit test for parser
  4. Copyright (c) 2007 by Michael Van Canneyt [email protected]
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {$mode objfpc}
  12. {$h+}
  13. {$codepage UTF8}
  14. unit testjsonparser;
  15. interface
  16. uses
  17. Classes, SysUtils, fpcunit, testregistry,fpjson,
  18. jsonscanner,jsonParser,testjsondata;
  19. Const
  20. DefaultOpts = [joUTF8,joStrict];
  21. type
  22. { TTestParser }
  23. TTestParser = class(TTestJSON)
  24. private
  25. FOptions : TJSONOptions;
  26. procedure CallNoHandlerStream;
  27. procedure DoDuplicate;
  28. procedure DoTestError(S: String; Options : TJSONOptions = DefaultOpts);
  29. procedure DoTestFloat(F: TJSONFloat); overload;
  30. procedure DoTestFloat(F: TJSONFloat; S: String); overload;
  31. procedure DoTestObject(S: String; const ElNames: array of String; DoJSONTest : Boolean = True);
  32. procedure DoTestString(S : String; AResult : String);
  33. procedure DoTestString(S : String);
  34. procedure DoTestArray(S: String; ACount: Integer; IgnoreJSON: Boolean=False);
  35. Procedure DoTestClass(S : String; AClass : TJSONDataClass);
  36. procedure CallNoHandler;
  37. procedure DoTrailingCommaErrorArray;
  38. procedure DoTrailingCommaErrorObject;
  39. Protected
  40. Procedure Setup; override;
  41. published
  42. procedure TestEmpty;
  43. procedure TestNull;
  44. procedure TestTrue;
  45. procedure TestFalse;
  46. procedure TestFloat;
  47. procedure TestInteger;
  48. procedure TestInt64;
  49. procedure TestString;
  50. procedure TestArray;
  51. procedure TestObject;
  52. procedure TestObjectError;
  53. procedure TestTrailingComma;
  54. procedure TestTrailingCommaErrorArray;
  55. procedure TestTrailingCommaErrorObject;
  56. procedure TestMixed;
  57. Procedure TestComment;
  58. procedure TestErrors;
  59. Procedure TestClasses;
  60. Procedure TestHandler;
  61. Procedure TestNoHandlerError;
  62. Procedure TestHandlerResult;
  63. Procedure TestHandlerResultStream;
  64. Procedure TestEmptyLine;
  65. Procedure TestStartEmptyLine;
  66. Procedure TestObjectEmptyLine;
  67. Procedure TestCommentLine;
  68. Procedure TestFirstLineComment;
  69. Procedure TestMultiLineComment;
  70. Procedure TestIgnoreDuplicates;
  71. Procedure TestNoIgnoreDuplicates;
  72. end;
  73. implementation
  74. procedure TTestParser.TestEmpty;
  75. Var
  76. P : TJSONParser;
  77. J : TJSONData;
  78. begin
  79. P:=TJSONParser.Create('',[joUTF8]);
  80. Try
  81. J:=P.Parse;
  82. If (J<>Nil) then
  83. Fail('Empty returns Nil');
  84. Finally
  85. FreeAndNil(J);
  86. FreeAndNil(P);
  87. end;
  88. end;
  89. procedure TTestParser.TestInteger;
  90. Var
  91. P : TJSONParser;
  92. J : TJSONData;
  93. begin
  94. P:=TJSONParser.Create('1',[joUTF8]);
  95. Try
  96. J:=P.Parse;
  97. If (J=Nil) then
  98. Fail('Parse of 1 fails');
  99. TestJSONType(J,jtNumber);
  100. TestAsInteger(J,1);
  101. Finally
  102. FreeAndNil(J);
  103. FreeAndNil(P);
  104. end;
  105. end;
  106. procedure TTestParser.TestInt64;
  107. Var
  108. P : TJSONParser;
  109. J : TJSONData;
  110. begin
  111. P:=TJSONParser.Create('123456789012345',[joUTF8]);
  112. Try
  113. J:=P.Parse;
  114. If (J=Nil) then
  115. Fail('Parse of 123456789012345 fails');
  116. TestJSONType(J,jtNumber);
  117. TestAsInt64(J,123456789012345);
  118. Finally
  119. FreeAndNil(J);
  120. FreeAndNil(P);
  121. end;
  122. end;
  123. procedure TTestParser.TestNull;
  124. Var
  125. P : TJSONParser;
  126. J : TJSONData;
  127. begin
  128. P:=TJSONParser.Create('null',[joUTF8]);
  129. Try
  130. J:=P.Parse;
  131. If (J=Nil) then
  132. Fail('Parse of null fails');
  133. TestJSONType(J,jtNull);
  134. Finally
  135. FreeAndNil(J);
  136. FreeAndNil(P);
  137. end;
  138. end;
  139. procedure TTestParser.TestTrue;
  140. Var
  141. P : TJSONParser;
  142. J : TJSONData;
  143. begin
  144. P:=TJSONParser.Create('true',[joUTF8]);
  145. Try
  146. J:=P.Parse;
  147. If (J=Nil) then
  148. Fail('Parse of True fails');
  149. TestJSONType(J,jtBoolean);
  150. TestAsBoolean(J,True);
  151. Finally
  152. FreeAndNil(J);
  153. FreeAndNil(P);
  154. end;
  155. end;
  156. procedure TTestParser.TestFalse;
  157. Var
  158. P : TJSONParser;
  159. J : TJSONData;
  160. begin
  161. P:=TJSONParser.Create('false',[joUTF8]);
  162. Try
  163. J:=P.Parse;
  164. If (J=Nil) then
  165. Fail('Parse of False fails');
  166. TestJSONType(J,jtBoolean);
  167. TestAsBoolean(J,False);
  168. Finally
  169. FreeAndNil(J);
  170. FreeAndNil(P);
  171. end;
  172. end;
  173. procedure TTestParser.TestFloat;
  174. begin
  175. DoTestFloat(1.2);
  176. DoTestFloat(-1.2);
  177. DoTestFloat(0);
  178. DoTestFloat(1.2e1);
  179. DoTestFloat(-1.2e1);
  180. DoTestFloat(0);
  181. DoTestFloat(1.2,'1.2');
  182. DoTestFloat(-1.2,'-1.2');
  183. DoTestFloat(0,'0.0');
  184. end;
  185. procedure TTestParser.TestString;
  186. Const
  187. // Glowing star in UTF8
  188. GlowingStar = #$F0#$9F#$8C#$9F;
  189. begin
  190. DoTestString('A string');
  191. DoTestString('');
  192. DoTestString('\"');
  193. DoTestString('\u00f8','ø'); // this is ø
  194. DoTestString('\u00f8\"','ø"'); // this is ø"
  195. // Writeln(GlowingStar);
  196. DoTestString('\ud83c\udf1f',GlowingStar);
  197. end;
  198. procedure TTestParser.TestArray;
  199. Var
  200. S1,S2,S3 : String;
  201. begin
  202. DoTestArray('[]',0);
  203. DoTestArray('[null]',1);
  204. DoTestArray('[true]',1);
  205. DoTestArray('[false]',1);
  206. DoTestArray('[1]',1);
  207. DoTestArray('[1, 2]',2);
  208. DoTestArray('[1, 2, 3]',3);
  209. DoTestArray('[1234567890123456]',1);
  210. DoTestArray('[1234567890123456, 2234567890123456]',2);
  211. DoTestArray('[1234567890123456, 2234567890123456, 3234567890123456]',3);
  212. Str(12/10,S1);
  213. Delete(S1,1,1);
  214. Str(34/10,S2);
  215. Delete(S2,1,1);
  216. Str(34/10,S3);
  217. Delete(S3,1,1);
  218. DoTestArray('['+S1+']',1,true);
  219. DoTestArray('['+S1+', '+S2+']',2,true);
  220. DoTestArray('['+S1+', '+S2+', '+S3+']',3,true);
  221. DoTestArray('["A string"]',1);
  222. DoTestArray('["A string", "Another string"]',2);
  223. DoTestArray('["A string", "Another string", "Yet another string"]',3);
  224. DoTestArray('[null, false]',2);
  225. DoTestArray('[true, false]',2);
  226. DoTestArray('[null, 1]',2);
  227. DoTestArray('[1, "A string"]',2);
  228. DoTestArray('[1, []]',2);
  229. DoTestArray('[1, [1, 2]]',2);
  230. end;
  231. procedure TTestParser.TestTrailingComma;
  232. begin
  233. FOptions:=[joIgnoreTrailingComma];
  234. DoTestArray('[1, 2,]',2,True);
  235. DoTestObject('{ "a" : 1, }',['a'],False);
  236. end;
  237. procedure TTestParser.TestTrailingCommaErrorArray;
  238. begin
  239. AssertException('Need joIgnoreTrailingComma in options to allow trailing comma',EJSONParser,@DoTrailingCommaErrorArray) ;
  240. end;
  241. procedure TTestParser.TestTrailingCommaErrorObject;
  242. begin
  243. AssertException('Need joIgnoreTrailingComma in options to allow trailing comma',EJSONParser,@DoTrailingCommaErrorObject);
  244. end;
  245. procedure TTestParser.DoTrailingCommaErrorArray;
  246. begin
  247. DoTestArray('[1, 2,]',2,True);
  248. end;
  249. procedure TTestParser.DoTrailingCommaErrorObject;
  250. begin
  251. DoTestObject('{ "a" : 1, }',['a'],False);
  252. end;
  253. procedure TTestParser.TestMixed;
  254. Const
  255. SAddr ='{ "addressbook": { "name": "Mary Lebow", '+
  256. ' "address": {'+
  257. ' "street": "5 Main Street",'+LineEnding+
  258. ' "city": "San Diego, CA",'+LineEnding+
  259. ' "zip": 91912'+LineEnding+
  260. ' },'+LineEnding+
  261. ' "phoneNumbers": [ '+LineEnding+
  262. ' "619 332-3452",'+LineEnding+
  263. ' "664 223-4667"'+LineEnding+
  264. ' ]'+LineEnding+
  265. ' }'+LineEnding+
  266. '}';
  267. begin
  268. DoTestArray('[1, {}]',2);
  269. DoTestArray('[1, { "a" : 1 }]',2);
  270. DoTestArray('[1, { "a" : 1 }, 1]',3);
  271. DoTestObject('{ "a" : [1, 2] }',['a']);
  272. DoTestObject('{ "a" : [1, 2], "B" : { "c" : "d" } }',['a','B']);
  273. DoTestObject(SAddr,['addressbook'],False);
  274. end;
  275. procedure TTestParser.TestComment;
  276. begin
  277. FOptions:=[joComments];
  278. DoTestArray('/* */ [1, {}]',2,True);
  279. DoTestArray('//'+sLineBreak+'[1, { "a" : 1 }]',2,True);
  280. DoTestArray('/* '+sLineBreak+' */ [1, {}]',2,True);
  281. DoTestArray('/*'+sLineBreak+'*/ [1, {}]',2,True);
  282. DoTestArray('/*'+sLineBreak+'*/ [1, {}]',2,True);
  283. DoTestArray('/*'+sLineBreak+'*'+sLineBreak+'*/ [1, {}]',2,True);
  284. DoTestArray('/**'+sLineBreak+'**'+sLineBreak+'**/ [1, {}]',2,True);
  285. DoTestArray('/* */ [1, {}]',2,True);
  286. DoTestArray('[1, { "a" : 1 }]//'+sLineBreak,2,True);
  287. DoTestArray('[1, {}]/* '+sLineBreak+' */ ',2,True);
  288. DoTestArray('[1, {}]/*'+sLineBreak+'*/ ',2,True);
  289. DoTestArray('[1, {}]/*'+sLineBreak+'*/ ',2,True);
  290. DoTestArray('[1, {}]/*'+sLineBreak+'*'+sLineBreak+'*/ ',2,True);
  291. DoTestArray(' [1, {}]/**'+sLineBreak+'**'+sLineBreak+'**/',2,True);
  292. end;
  293. procedure TTestParser.TestObject;
  294. begin
  295. DoTestObject('{}',[]);
  296. DoTestObject('{ "a" : 1 }',['a']);
  297. DoTestObject('{ "a" : 1, "B" : "String" }',['a','B']);
  298. DoTestObject('{ "a" : 1, "B" : {} }',['a','B']);
  299. DoTestObject('{ "a" : 1, "B" : { "c" : "d" } }',['a','B']);
  300. end;
  301. procedure TTestParser.TestObjectError;
  302. begin
  303. DoTestError('{ "name" : value }',[joUTF8]);
  304. end;
  305. procedure TTestParser.DoTestObject(S: String; const ElNames: array of String;
  306. DoJSONTest: Boolean);
  307. Var
  308. P : TJSONParser;
  309. J : TJSONData;
  310. O : TJSONObject;
  311. I : Integer;
  312. begin
  313. J:=Nil;
  314. P:=TJSONParser.Create(S,[joUTF8]);
  315. Try
  316. P.Options:=FOptions;
  317. J:=P.Parse;
  318. If (J=Nil) then
  319. Fail('Parse of object "'+S+'" fails');
  320. TestJSONType(J,jtObject);
  321. TestItemCount(J,High(ElNames)-Low(ElNames)+1);
  322. O:=TJSONObject(J);
  323. For I:=Low(ElNames) to High(ElNames) do
  324. AssertEquals(Format('Element %d name',[I-Low(Elnames)])
  325. ,ElNames[i], O.Names[I-Low(ElNames)]);
  326. If DoJSONTest then
  327. self.TestJSON(J,S);
  328. Finally
  329. FreeAndNil(J);
  330. FreeAndNil(P);
  331. end;
  332. end;
  333. procedure TTestParser.DoTestArray(S : String; ACount : Integer; IgnoreJSON : Boolean = False);
  334. Var
  335. P : TJSONParser;
  336. J : TJSONData;
  337. begin
  338. J:=Nil;
  339. P:=TJSONParser.Create(S,[joComments]);
  340. Try
  341. P.Options:=FOptions;
  342. J:=P.Parse;
  343. If (J=Nil) then
  344. Fail('Parse of array "'+S+'" fails');
  345. TestJSONType(J,jtArray);
  346. TestItemCount(J,ACount);
  347. if not IgnoreJSON then
  348. TestJSON(J,S);
  349. Finally
  350. FreeAndNil(J);
  351. FreeAndNil(P);
  352. end;
  353. end;
  354. procedure TTestParser.DoTestClass(S: String; AClass: TJSONDataClass);
  355. Var
  356. P : TJSONParser;
  357. D : TJSONData;
  358. begin
  359. P:=TJSONParser.Create(S,[joUTF8]);
  360. try
  361. D:=P.Parse;
  362. try
  363. AssertEquals('Correct class for '+S+' : ',AClass,D.ClassType);
  364. finally
  365. D.Free
  366. end;
  367. finally
  368. P.Free;
  369. end;
  370. end;
  371. procedure TTestParser.TestErrors;
  372. begin
  373. DoTestError('1Tru');
  374. DoTestError('a');
  375. DoTestError('"b');
  376. DoTestError('b"');
  377. DoTestError('{"a" : }');
  378. DoTestError('{"a" : ""');
  379. DoTestError('{"a : ""');
  380. DoTestError('[1,]');
  381. DoTestError('[,]');
  382. DoTestError('[,,]');
  383. DoTestError('[1,,]');
  384. end;
  385. procedure TTestParser.TestClasses;
  386. begin
  387. SetMyInstanceTypes;
  388. DoTestClass('null',TMyNull);
  389. DoTestClass('true',TMyBoolean);
  390. DoTestClass('1',TMyInteger);
  391. DoTestClass('1.2',TMyFloat);
  392. DoTestClass('123456789012345',TMyInt64);
  393. DoTestClass('"tata"',TMyString);
  394. DoTestClass('{}',TMyObject);
  395. DoTestClass('[]',TMyArray);
  396. end;
  397. procedure TTestParser.CallNoHandler;
  398. begin
  399. GetJSON('1',True).Free;
  400. end;
  401. procedure TTestParser.Setup;
  402. begin
  403. inherited Setup;
  404. FOptions:=[];
  405. end;
  406. procedure TTestParser.CallNoHandlerStream;
  407. Var
  408. S : TStringStream;
  409. begin
  410. S:=TstringStream.Create('1');
  411. try
  412. GetJSON(S,True).Free;
  413. finally
  414. S.Free;
  415. end;
  416. end;
  417. procedure TTestParser.TestHandler;
  418. begin
  419. AssertNotNull('Handler installed',GetJSONParserHandler);
  420. end;
  421. procedure TTestParser.TestNoHandlerError;
  422. Var
  423. H : TJSONParserHandler;
  424. HS : TJSONStringParserHandler;
  425. begin
  426. H:=GetJSONParserHandler;
  427. HS:=GetJSONStringParserHandler;
  428. try
  429. AssertSame('SetJSONParserHandler returns previous handler',H,SetJSONParserHandler(Nil));
  430. AssertSame('SetJSONStringParserHandler returns previous handler',HS,SetJSONStringParserHandler(Nil));
  431. AssertException('No handler raises exception',EJSON,@CallNoHandler);
  432. AssertException('No handler raises exception',EJSON,@CallNoHandlerStream);
  433. finally
  434. SetJSONParserHandler(H);
  435. SetJSONStringParserHandler(HS);
  436. end;
  437. end;
  438. procedure TTestParser.TestHandlerResult;
  439. Var
  440. D : TJSONData;
  441. begin
  442. D:=GetJSON('"123"');
  443. try
  444. AssertEquals('Have correct string','123',D.AsString);
  445. finally
  446. D.Free;
  447. end;
  448. end;
  449. procedure TTestParser.TestHandlerResultStream;
  450. Var
  451. D : TJSONData;
  452. S : TStream;
  453. begin
  454. {$IF SIZEOF(Char)=2}
  455. S:=TStringStream.Create(UTF8Encode('"123"'));
  456. {$else}
  457. S:=TStringStream.Create('"123"');
  458. {$ENDIF}
  459. try
  460. D:=GetJSON(S,False);
  461. try
  462. AssertEquals('Have correct string','123',D.AsString);
  463. finally
  464. D.Free;
  465. end;
  466. finally
  467. S.Free;
  468. end;
  469. end;
  470. procedure TTestParser.TestEmptyLine;
  471. // Bug report 36037
  472. Const MyJSON =
  473. ' {'+sLineBreak+
  474. ' "pylib__linux" : "libpython3.7m.so.1.0",'+sLineBreak+
  475. ' "ui_toolbar_theme": "default_24x24",'+sLineBreak+
  476. ' "ui_toolbar_show" : true,'+sLineBreak+
  477. ' "font_name__linux" : "DejaVu Sans Mono",'+sLineBreak+
  478. ' "font_size__linux" : 10,'+sLineBreak+
  479. ' "ui_listbox_fuzzy": false,'+sLineBreak+
  480. ' "ui_max_size_lexer": 5,'+sLineBreak+
  481. ' "find_separate_form": false,'+sLineBreak+sLineBreak+
  482. '}';
  483. var
  484. J : TJSONData;
  485. begin
  486. With TJSONParser.Create(MyJSON,[joUTF8,joIgnoreTrailingComma]) do
  487. Try
  488. J:=Parse;
  489. J.Free;
  490. Finally
  491. Free;
  492. end;
  493. end;
  494. procedure TTestParser.TestStartEmptyLine;
  495. // Bug ID 37352: case 1
  496. const
  497. ENDLINE = #$0d#$0a;
  498. Const
  499. MyJSON = ENDLINE+
  500. '{'+ENDLINE+
  501. '"version":100,'+ENDLINE+
  502. // '//comment'+ENDLINE+
  503. '"value":200'+ENDLINE+
  504. '}'+ENDLINE;
  505. var
  506. J : TJSONData;
  507. begin
  508. With TJSONParser.Create(MyJSON,[joComments]) do
  509. Try
  510. J:=Parse;
  511. J.Free;
  512. Finally
  513. Free;
  514. end;
  515. end;
  516. procedure TTestParser.TestObjectEmptyLine;
  517. // Bug ID 37352: case 2
  518. const
  519. ENDLINE = #$0d#$0a;
  520. Const
  521. MyJSON = '{'+ENDLINE+
  522. ''+ENDLINE+
  523. '"version":100, //comment'+ENDLINE+
  524. '"value":200'+ENDLINE+
  525. '}'+ENDLINE;
  526. var
  527. J : TJSONData;
  528. begin
  529. With TJSONParser.Create(MyJSON,[joComments]) do
  530. Try
  531. J:=Parse;
  532. J.Free;
  533. Finally
  534. Free;
  535. end;
  536. end;
  537. procedure TTestParser.TestCommentLine;
  538. // Bug ID 37352: case 3
  539. const
  540. ENDLINE = #$0d#$0a;
  541. Const
  542. MyJSON =
  543. ENDLINE+
  544. '{'+ENDLINE+
  545. '"version":100, //comment'+ENDLINE+
  546. '"value":200'+ENDLINE+
  547. '}'+ENDLINE;
  548. var
  549. J : TJSONData;
  550. begin
  551. With TJSONParser.Create(MyJSON,[joComments]) do
  552. Try
  553. J:=Parse;
  554. J.Free;
  555. Finally
  556. Free;
  557. end;
  558. end;
  559. procedure TTestParser.TestFirstLineComment;
  560. // New case
  561. const
  562. ENDLINE = #$0d#$0a;
  563. Const
  564. MyJSON =
  565. '//comment1'+ENDLINE+
  566. '{'+ENDLINE+
  567. '"version":100, //comment2'+ENDLINE+
  568. '"value":200'+ENDLINE+
  569. '}'+ENDLINE;
  570. var
  571. J : TJSONData;
  572. begin
  573. With TJSONParser.Create(MyJSON,[joComments]) do
  574. Try
  575. J:=Parse;
  576. J.Free;
  577. Finally
  578. Free;
  579. end;
  580. end;
  581. procedure TTestParser.TestMultiLineComment;
  582. // Issue 37367
  583. const
  584. ENDLINE = #$0d#$0a;
  585. Const
  586. MyJSON =
  587. '/* long comment'+ENDLINE+
  588. ''+ENDLINE+
  589. ' error'+ENDLINE+
  590. '*/'+ENDLINE+
  591. '{'+ENDLINE+
  592. ' "version":100, //coment2 without comment2 works well '+ENDLINE+
  593. ' "valor":200 /*comment 3'+ENDLINE+
  594. ' line 2'+ENDLINE+
  595. ' */'+ENDLINE+
  596. '}'+ENDLINE;
  597. var
  598. J : TJSONData;
  599. begin
  600. With TJSONParser.Create(MyJSON,[joComments]) do
  601. Try
  602. J:=Parse;
  603. J.Free;
  604. Finally
  605. Free;
  606. end;
  607. end;
  608. procedure TTestParser.TestIgnoreDuplicates;
  609. Const
  610. MyJSON =
  611. '{ "a":100, "b": 20, "a":300} ';
  612. var
  613. J : TJSONData;
  614. begin
  615. With TJSONParser.Create(MyJSON,[joIgnoreDuplicates]) do
  616. Try
  617. J:=Parse;
  618. AssertEquals('Correct class',TJSONObject,J.ClassType);
  619. AssertEquals('Correct value',100,TJSONObject(J).Get('a',0));
  620. J.Free;
  621. Finally
  622. Free;
  623. end;
  624. end;
  625. procedure TTestParser.DoDuplicate;
  626. Const
  627. MyJSON =
  628. '{ "a":100, "b": 20, "a":300} ';
  629. var
  630. J : TJSONData;
  631. begin
  632. With TJSONParser.Create(MyJSON,[]) do
  633. Try
  634. J:=Parse;
  635. J.Free;
  636. Finally
  637. Free;
  638. end;
  639. end;
  640. procedure TTestParser.TestNoIgnoreDuplicates;
  641. begin
  642. AssertException('No duplicates allowed',EJSON,@DoDuplicate);
  643. end;
  644. procedure TTestParser.DoTestError(S : String; Options : TJSONOptions = DefaultOpts);
  645. Var
  646. P : TJSONParser;
  647. J : TJSONData;
  648. ParseOK : Boolean;
  649. N : String;
  650. begin
  651. ParseOK:=False;
  652. P:=TJSONParser.Create(S,[joUTF8]);
  653. P.OPtions:=Options;
  654. J:=Nil;
  655. Try
  656. Try
  657. Repeat
  658. FreeAndNil(J);
  659. J:=P.Parse;
  660. ParseOK:=True;
  661. If (J<>Nil) then
  662. N:=J.ClassName;
  663. Until (J=Nil)
  664. Finally
  665. FreeAndNil(J);
  666. FreeAndNil(P);
  667. end;
  668. except
  669. ParseOk:=False;
  670. end;
  671. If ParseOK then
  672. Fail('Parse of JSON string "'+S+'" should fail, but returned '+N);
  673. end;
  674. procedure TTestParser.DoTestString(S: String);
  675. begin
  676. DoTestString(S,JSONStringToString(S));
  677. end;
  678. procedure TTestParser.DoTestString(S: String; AResult : String);
  679. Var
  680. P : TJSONParser;
  681. J : TJSONData;
  682. begin
  683. P:=TJSONParser.Create('"'+S+'"',[joUTF8]);
  684. Try
  685. J:=P.Parse;
  686. If (J=Nil) then
  687. Fail('Parse of string "'+S+'" fails');
  688. TestJSONType(J,jtString);
  689. TestAsString(J,aResult);
  690. if Pos('\u',S)=0 then
  691. TestJSON(J,'"'+S+'"');
  692. Finally
  693. FreeAndNil(J);
  694. FreeAndNil(P);
  695. end;
  696. end;
  697. procedure TTestParser.DoTestFloat(F : TJSONFloat);
  698. Var
  699. S : String;
  700. begin
  701. Str(F,S);
  702. DoTestFloat(F,S);
  703. end;
  704. procedure TTestParser.DoTestFloat(F : TJSONFloat; S : String);
  705. Var
  706. P : TJSONParser;
  707. J : TJSONData;
  708. begin
  709. P:=TJSONParser.Create(S,[joUTF8]);
  710. Try
  711. J:=P.Parse;
  712. If (J=Nil) then
  713. Fail('Parse of float '+S+' fails');
  714. TestJSONType(J,jtNumber);
  715. TestAsFloat(J,F);
  716. Finally
  717. FreeAndNil(J);
  718. FreeAndNil(P);
  719. end;
  720. end;
  721. initialization
  722. RegisterTest(TTestParser);
  723. end.