testjsonparser.pas 17 KB

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