filter.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773
  1. // ArduinoJson - https://arduinojson.org
  2. // Copyright © 2014-2022, Benoit BLANCHON
  3. // MIT License
  4. #define ARDUINOJSON_ENABLE_COMMENTS 1
  5. #include <ArduinoJson.h>
  6. #include <catch.hpp>
  7. #include <sstream>
  8. #include <string>
  9. TEST_CASE("Filtering") {
  10. struct TestCase {
  11. const char* input;
  12. const char* filter;
  13. uint8_t nestingLimit;
  14. DeserializationError error;
  15. const char* output;
  16. size_t memoryUsage;
  17. };
  18. // clang-format off
  19. TestCase testCases[] = {
  20. {
  21. "{\"hello\":\"world\"}", // 1. input
  22. "null", // 2. filter
  23. 10, // 3. nestingLimit
  24. DeserializationError::Ok, // 4. error
  25. "null", // 5. output
  26. 0 // 6. memoryUsage
  27. },
  28. {
  29. "{\"hello\":\"world\"}",
  30. "false",
  31. 10,
  32. DeserializationError::Ok,
  33. "null",
  34. 0
  35. },
  36. {
  37. "{\"abcdefg\":\"hijklmn\"}",
  38. "true",
  39. 10,
  40. DeserializationError::Ok,
  41. "{\"abcdefg\":\"hijklmn\"}",
  42. JSON_OBJECT_SIZE(1) + 16
  43. },
  44. {
  45. "{\"hello\":\"world\"}",
  46. "{}",
  47. 10,
  48. DeserializationError::Ok,
  49. "{}",
  50. JSON_OBJECT_SIZE(0)
  51. },
  52. {
  53. // Input in an object, but filter wants an array
  54. "{\"hello\":\"world\"}",
  55. "[]",
  56. 10,
  57. DeserializationError::Ok,
  58. "null",
  59. 0
  60. },
  61. {
  62. // Member is a string, but filter wants an array
  63. "{\"example\":\"example\"}",
  64. "{\"example\":[true]}",
  65. 10,
  66. DeserializationError::Ok,
  67. "{\"example\":null}",
  68. JSON_OBJECT_SIZE(1) + 8
  69. },
  70. {
  71. // Input is an array, but filter wants an object
  72. "[\"hello\",\"world\"]",
  73. "{}",
  74. 10,
  75. DeserializationError::Ok,
  76. "null",
  77. 0
  78. },
  79. {
  80. // Input is a bool, but filter wants an object
  81. "true",
  82. "{}",
  83. 10,
  84. DeserializationError::Ok,
  85. "null",
  86. 0
  87. },
  88. {
  89. // Input is a string, but filter wants an object
  90. "\"hello\"",
  91. "{}",
  92. 10,
  93. DeserializationError::Ok,
  94. "null",
  95. 0
  96. },
  97. {
  98. // skip an integer
  99. "{\"an_integer\":666,example:42}",
  100. "{\"example\":true}",
  101. 10,
  102. DeserializationError::Ok,
  103. "{\"example\":42}",
  104. JSON_OBJECT_SIZE(1) + 8
  105. },
  106. {
  107. // skip a float
  108. "{\"a_float\":12.34e-6,example:42}",
  109. "{\"example\":true}",
  110. 10,
  111. DeserializationError::Ok,
  112. "{\"example\":42}",
  113. JSON_OBJECT_SIZE(1) + 8
  114. },
  115. {
  116. // can skip a boolean
  117. "{\"a_bool\":false,example:42}",
  118. "{\"example\":true}",
  119. 10,
  120. DeserializationError::Ok,
  121. "{\"example\":42}",
  122. JSON_OBJECT_SIZE(1) + 8
  123. },
  124. {
  125. // can skip a double-quoted string
  126. "{\"a_double_quoted_string\":\"hello\",example:42}",
  127. "{\"example\":true}",
  128. 10,
  129. DeserializationError::Ok,
  130. "{\"example\":42}",
  131. JSON_OBJECT_SIZE(1) + 8
  132. },
  133. {
  134. // can skip a single-quoted string
  135. "{\"a_single_quoted_string\":'hello',example:42}",
  136. "{\"example\":true}",
  137. 10,
  138. DeserializationError::Ok,
  139. "{\"example\":42}",
  140. JSON_OBJECT_SIZE(1) + 8
  141. },
  142. {
  143. // can skip an empty array
  144. "{\"an_empty_array\":[],example:42}",
  145. "{\"example\":true}",
  146. 10,
  147. DeserializationError::Ok,
  148. "{\"example\":42}",
  149. JSON_OBJECT_SIZE(1) + 8
  150. },
  151. {
  152. // can skip an empty array with spaces in it
  153. "{\"an_empty_array\":[\t],example:42}",
  154. "{\"example\":true}",
  155. 10,
  156. DeserializationError::Ok,
  157. "{\"example\":42}",
  158. JSON_OBJECT_SIZE(1) + 8
  159. },
  160. {
  161. // can skip an array
  162. "{\"an_array\":[1,2,3],example:42}",
  163. "{\"example\":true}",
  164. 10,
  165. DeserializationError::Ok,
  166. "{\"example\":42}",
  167. JSON_OBJECT_SIZE(1) + 8
  168. },
  169. {
  170. // can skip an array with spaces in it
  171. "{\"an_array\": [ 1 , 2 , 3 ] ,example:42}",
  172. "{\"example\":true}",
  173. 10,
  174. DeserializationError::Ok,
  175. "{\"example\":42}",
  176. JSON_OBJECT_SIZE(1) + 8
  177. },
  178. {
  179. // can skip an empty object
  180. "{\"an_empty_object\":{},example:42}",
  181. "{\"example\":true}",
  182. 10,
  183. DeserializationError::Ok,
  184. "{\"example\":42}",
  185. JSON_OBJECT_SIZE(1) + 8
  186. },
  187. {
  188. // can skip an empty object with spaces in it
  189. "{\"an_empty_object\":{ },example:42}",
  190. "{\"example\":true}",
  191. 10,
  192. DeserializationError::Ok,
  193. "{\"example\":42}",
  194. JSON_OBJECT_SIZE(1) + 8
  195. },
  196. {
  197. // can skip an object
  198. "{\"an_object\":{a:1,'b':2,\"c\":3},example:42}",
  199. "{\"example\":true}",
  200. 10,
  201. DeserializationError::Ok,
  202. "{\"example\":42}",
  203. JSON_OBJECT_SIZE(1) + 8
  204. },
  205. {
  206. // skip an object with spaces in it
  207. "{\"an_object\" : { a : 1 , 'b' : 2 , \"c\" : 3 } ,example:42}",
  208. "{\"example\":true}",
  209. 10,
  210. DeserializationError::Ok,
  211. "{\"example\":42}",
  212. JSON_OBJECT_SIZE(1) + 8
  213. },
  214. {
  215. "{\"an_integer\": 0,\"example\":{\"type\":\"int\",\"outcome\":42}}",
  216. "{\"example\":{\"outcome\":true}}",
  217. 10,
  218. DeserializationError::Ok,
  219. "{\"example\":{\"outcome\":42}}",
  220. 2 * JSON_OBJECT_SIZE(1) + 16
  221. },
  222. {
  223. // wildcard
  224. "{\"example\":{\"type\":\"int\",\"outcome\":42}}",
  225. "{\"*\":{\"outcome\":true}}",
  226. 10,
  227. DeserializationError::Ok,
  228. "{\"example\":{\"outcome\":42}}",
  229. 2 * JSON_OBJECT_SIZE(1) + 16
  230. },
  231. {
  232. // exclusion filter (issue #1628)
  233. "{\"example\":1,\"ignored\":2}",
  234. "{\"*\":true,\"ignored\":false}",
  235. 10,
  236. DeserializationError::Ok,
  237. "{\"example\":1}",
  238. JSON_OBJECT_SIZE(1) + 8
  239. },
  240. {
  241. // only the first element of array counts
  242. "[1,2,3]",
  243. "[true, false]",
  244. 10,
  245. DeserializationError::Ok,
  246. "[1,2,3]",
  247. JSON_ARRAY_SIZE(3)
  248. },
  249. {
  250. // only the first element of array counts
  251. "[1,2,3]",
  252. "[false, true]",
  253. 10,
  254. DeserializationError::Ok,
  255. "[]",
  256. JSON_ARRAY_SIZE(0)
  257. },
  258. {
  259. // filter members of object in array
  260. "[{\"example\":1,\"ignore\":2},{\"example\":3,\"ignore\":4}]",
  261. "[{\"example\":true}]",
  262. 10,
  263. DeserializationError::Ok,
  264. "[{\"example\":1},{\"example\":3}]",
  265. JSON_ARRAY_SIZE(2) + 2 * JSON_OBJECT_SIZE(1) + 8
  266. },
  267. {
  268. "[',2,3]",
  269. "[false,true]",
  270. 10,
  271. DeserializationError::IncompleteInput,
  272. "[]",
  273. JSON_ARRAY_SIZE(0)
  274. },
  275. {
  276. "[\",2,3]",
  277. "[false,true]",
  278. 10,
  279. DeserializationError::IncompleteInput,
  280. "[]",
  281. JSON_ARRAY_SIZE(0)
  282. },
  283. {
  284. // detect errors in skipped value
  285. "[!,2,\\]",
  286. "[false]",
  287. 10,
  288. DeserializationError::InvalidInput,
  289. "[]",
  290. JSON_ARRAY_SIZE(0)
  291. },
  292. {
  293. // detect incomplete string event if it's skipped
  294. "\"ABC",
  295. "false",
  296. 10,
  297. DeserializationError::IncompleteInput,
  298. "null",
  299. 0
  300. },
  301. {
  302. // detect incomplete string event if it's skipped
  303. "'ABC",
  304. "false",
  305. 10,
  306. DeserializationError::IncompleteInput,
  307. "null",
  308. 0
  309. },
  310. {
  311. // handle escaped quotes
  312. "'A\\'BC'",
  313. "false",
  314. 10,
  315. DeserializationError::Ok,
  316. "null",
  317. 0
  318. },
  319. {
  320. // handle escaped quotes
  321. "\"A\\\"BC\"",
  322. "false",
  323. 10,
  324. DeserializationError::Ok,
  325. "null",
  326. 0
  327. },
  328. {
  329. // detect incomplete string in presence of escaped quotes
  330. "'A\\'BC",
  331. "false",
  332. 10,
  333. DeserializationError::IncompleteInput,
  334. "null",
  335. 0
  336. },
  337. {
  338. // detect incomplete string in presence of escaped quotes
  339. "\"A\\\"BC",
  340. "false",
  341. 10,
  342. DeserializationError::IncompleteInput,
  343. "null",
  344. 0
  345. },
  346. {
  347. // skip empty array
  348. "[]",
  349. "false",
  350. 10,
  351. DeserializationError::Ok,
  352. "null",
  353. 0
  354. },
  355. {
  356. // skip empty array with spaces
  357. " [ ] ",
  358. "false",
  359. 10,
  360. DeserializationError::Ok,
  361. "null",
  362. 0
  363. },
  364. {
  365. // bubble up element error even if array is skipped
  366. "[1,'2,3]",
  367. "false",
  368. 10,
  369. DeserializationError::IncompleteInput,
  370. "null",
  371. 0
  372. },
  373. {
  374. // bubble up member error even if object is skipped
  375. "{'hello':'worl}",
  376. "false",
  377. 10,
  378. DeserializationError::IncompleteInput,
  379. "null",
  380. 0
  381. },
  382. {
  383. // bubble up colon error even if object is skipped
  384. "{'hello','world'}",
  385. "false",
  386. 10,
  387. DeserializationError::InvalidInput,
  388. "null",
  389. 0
  390. },
  391. {
  392. // bubble up key error even if object is skipped
  393. "{'hello:1}",
  394. "false",
  395. 10,
  396. DeserializationError::IncompleteInput,
  397. "null",
  398. 0
  399. },
  400. {
  401. // detect invalid value in skipped object
  402. "{'hello':!}",
  403. "false",
  404. 10,
  405. DeserializationError::InvalidInput,
  406. "null",
  407. 0
  408. },
  409. {
  410. // ignore invalid value in skipped object
  411. "{'hello':\\}",
  412. "false",
  413. 10,
  414. DeserializationError::InvalidInput,
  415. "null",
  416. 0
  417. },
  418. {
  419. // check nesting limit even for ignored objects
  420. "{}",
  421. "false",
  422. 0,
  423. DeserializationError::TooDeep,
  424. "null",
  425. 0
  426. },
  427. {
  428. // check nesting limit even for ignored objects
  429. "{'hello':{}}",
  430. "false",
  431. 1,
  432. DeserializationError::TooDeep,
  433. "null",
  434. 0
  435. },
  436. {
  437. // check nesting limit even for ignored values in objects
  438. "{'hello':{}}",
  439. "{}",
  440. 1,
  441. DeserializationError::TooDeep,
  442. "{}",
  443. JSON_OBJECT_SIZE(0)
  444. },
  445. {
  446. // check nesting limit even for ignored arrays
  447. "[]",
  448. "false",
  449. 0,
  450. DeserializationError::TooDeep,
  451. "null",
  452. 0
  453. },
  454. {
  455. // check nesting limit even for ignored arrays
  456. "[[]]",
  457. "false",
  458. 1,
  459. DeserializationError::TooDeep,
  460. "null",
  461. 0
  462. },
  463. {
  464. // check nesting limit even for ignored values in arrays
  465. "[[]]",
  466. "[]",
  467. 1,
  468. DeserializationError::TooDeep,
  469. "[]",
  470. JSON_ARRAY_SIZE(0)
  471. },
  472. {
  473. // supports back-slash at the end of skipped string
  474. "\"hell\\",
  475. "false",
  476. 1,
  477. DeserializationError::IncompleteInput,
  478. "null",
  479. 0
  480. },
  481. {
  482. // invalid comment at after an element in a skipped array
  483. "[1/]",
  484. "false",
  485. 10,
  486. DeserializationError::InvalidInput,
  487. "null",
  488. 0
  489. },
  490. {
  491. // incomplete comment at after an element in a skipped array
  492. "[1/*]",
  493. "false",
  494. 10,
  495. DeserializationError::IncompleteInput,
  496. "null",
  497. 0
  498. },
  499. {
  500. // missing comma in a skipped array
  501. "[1 2]",
  502. "false",
  503. 10,
  504. DeserializationError::InvalidInput,
  505. "null",
  506. 0
  507. },
  508. {
  509. // invalid comment at the beginning of array
  510. "[/1]",
  511. "[false]",
  512. 10,
  513. DeserializationError::InvalidInput,
  514. "[]",
  515. JSON_ARRAY_SIZE(0)
  516. },
  517. {
  518. // incomplete comment at the begining of an array
  519. "[/*]",
  520. "[false]",
  521. 10,
  522. DeserializationError::IncompleteInput,
  523. "[]",
  524. JSON_ARRAY_SIZE(0)
  525. },
  526. {
  527. // invalid comment before key
  528. "{/1:2}",
  529. "{}",
  530. 10,
  531. DeserializationError::InvalidInput,
  532. "{}",
  533. JSON_OBJECT_SIZE(0)
  534. },
  535. {
  536. // incomplete comment before key
  537. "{/*:2}",
  538. "{}",
  539. 10,
  540. DeserializationError::IncompleteInput,
  541. "{}",
  542. JSON_OBJECT_SIZE(0)
  543. },
  544. {
  545. // invalid comment after key
  546. "{\"example\"/1:2}",
  547. "{}",
  548. 10,
  549. DeserializationError::InvalidInput,
  550. "{}",
  551. JSON_OBJECT_SIZE(0)
  552. },
  553. {
  554. // incomplete comment after key
  555. "{\"example\"/*:2}",
  556. "{}",
  557. 10,
  558. DeserializationError::IncompleteInput,
  559. "{}",
  560. JSON_OBJECT_SIZE(0)
  561. },
  562. {
  563. // invalid comment after colon
  564. "{\"example\":/12}",
  565. "{}",
  566. 10,
  567. DeserializationError::InvalidInput,
  568. "{}",
  569. JSON_OBJECT_SIZE(0)
  570. },
  571. {
  572. // incomplete comment after colon
  573. "{\"example\":/*2}",
  574. "{}",
  575. 10,
  576. DeserializationError::IncompleteInput,
  577. "{}",
  578. JSON_OBJECT_SIZE(0)
  579. },
  580. {
  581. // comment next to an integer
  582. "{\"ignore\":1//,\"example\":2\n}",
  583. "{\"example\":true}",
  584. 10,
  585. DeserializationError::Ok,
  586. "{}",
  587. JSON_OBJECT_SIZE(0)
  588. },
  589. {
  590. // invalid comment after opening brace of a skipped object
  591. "{/1:2}",
  592. "false",
  593. 10,
  594. DeserializationError::InvalidInput,
  595. "null",
  596. 0
  597. },
  598. {
  599. // incomplete after opening brace of a skipped object
  600. "{/*:2}",
  601. "false",
  602. 10,
  603. DeserializationError::IncompleteInput,
  604. "null",
  605. 0
  606. },
  607. {
  608. // invalid comment after key of a skipped object
  609. "{\"example\"/:2}",
  610. "false",
  611. 10,
  612. DeserializationError::InvalidInput,
  613. "null",
  614. 0
  615. },
  616. {
  617. // incomplete after after key of a skipped object
  618. "{\"example\"/*:2}",
  619. "false",
  620. 10,
  621. DeserializationError::IncompleteInput,
  622. "null",
  623. 0
  624. },
  625. {
  626. // invalid comment after value in a skipped object
  627. "{\"example\":2/}",
  628. "false",
  629. 10,
  630. DeserializationError::InvalidInput,
  631. "null",
  632. 0
  633. },
  634. {
  635. // incomplete after after value of a skipped object
  636. "{\"example\":2/*}",
  637. "false",
  638. 10,
  639. DeserializationError::IncompleteInput,
  640. "null",
  641. 0
  642. },
  643. }; // clang-format on
  644. for (size_t i = 0; i < sizeof(testCases) / sizeof(testCases[0]); i++) {
  645. CAPTURE(i);
  646. DynamicJsonDocument filter(256);
  647. DynamicJsonDocument doc(256);
  648. TestCase& tc = testCases[i];
  649. CAPTURE(tc.filter);
  650. REQUIRE(deserializeJson(filter, tc.filter) == DeserializationError::Ok);
  651. CAPTURE(tc.input);
  652. CAPTURE(tc.nestingLimit);
  653. CHECK(deserializeJson(doc, tc.input, DeserializationOption::Filter(filter),
  654. DeserializationOption::NestingLimit(
  655. tc.nestingLimit)) == tc.error);
  656. CHECK(doc.as<std::string>() == tc.output);
  657. CHECK(doc.memoryUsage() == tc.memoryUsage);
  658. }
  659. }
  660. TEST_CASE("Zero-copy mode") { // issue #1697
  661. char input[] = "{\"include\":42,\"exclude\":666}";
  662. StaticJsonDocument<256> filter;
  663. filter["include"] = true;
  664. StaticJsonDocument<256> doc;
  665. DeserializationError err =
  666. deserializeJson(doc, input, DeserializationOption::Filter(filter));
  667. REQUIRE(err == DeserializationError::Ok);
  668. CHECK(doc.as<std::string>() == "{\"include\":42}");
  669. }
  670. TEST_CASE("Overloads") {
  671. StaticJsonDocument<256> doc;
  672. StaticJsonDocument<256> filter;
  673. using namespace DeserializationOption;
  674. // deserializeJson(..., Filter)
  675. SECTION("const char*, Filter") {
  676. deserializeJson(doc, "{}", Filter(filter));
  677. }
  678. SECTION("const char*, size_t, Filter") {
  679. deserializeJson(doc, "{}", 2, Filter(filter));
  680. }
  681. SECTION("const std::string&, Filter") {
  682. deserializeJson(doc, std::string("{}"), Filter(filter));
  683. }
  684. SECTION("std::istream&, Filter") {
  685. std::stringstream s("{}");
  686. deserializeJson(doc, s, Filter(filter));
  687. }
  688. #ifdef HAS_VARIABLE_LENGTH_ARRAY
  689. SECTION("char[n], Filter") {
  690. int i = 4;
  691. char vla[i];
  692. strcpy(vla, "{}");
  693. deserializeJson(doc, vla, Filter(filter));
  694. }
  695. #endif
  696. // deserializeJson(..., Filter, NestingLimit)
  697. SECTION("const char*, Filter, NestingLimit") {
  698. deserializeJson(doc, "{}", Filter(filter), NestingLimit(5));
  699. }
  700. SECTION("const char*, size_t, Filter, NestingLimit") {
  701. deserializeJson(doc, "{}", 2, Filter(filter), NestingLimit(5));
  702. }
  703. SECTION("const std::string&, Filter, NestingLimit") {
  704. deserializeJson(doc, std::string("{}"), Filter(filter), NestingLimit(5));
  705. }
  706. SECTION("std::istream&, Filter, NestingLimit") {
  707. std::stringstream s("{}");
  708. deserializeJson(doc, s, Filter(filter), NestingLimit(5));
  709. }
  710. #ifdef HAS_VARIABLE_LENGTH_ARRAY
  711. SECTION("char[n], Filter, NestingLimit") {
  712. int i = 4;
  713. char vla[i];
  714. strcpy(vla, "{}");
  715. deserializeJson(doc, vla, Filter(filter), NestingLimit(5));
  716. }
  717. #endif
  718. // deserializeJson(..., NestingLimit, Filter)
  719. SECTION("const char*, NestingLimit, Filter") {
  720. deserializeJson(doc, "{}", NestingLimit(5), Filter(filter));
  721. }
  722. SECTION("const char*, size_t, NestingLimit, Filter") {
  723. deserializeJson(doc, "{}", 2, NestingLimit(5), Filter(filter));
  724. }
  725. SECTION("const std::string&, NestingLimit, Filter") {
  726. deserializeJson(doc, std::string("{}"), NestingLimit(5), Filter(filter));
  727. }
  728. SECTION("std::istream&, NestingLimit, Filter") {
  729. std::stringstream s("{}");
  730. deserializeJson(doc, s, NestingLimit(5), Filter(filter));
  731. }
  732. #ifdef HAS_VARIABLE_LENGTH_ARRAY
  733. SECTION("char[n], NestingLimit, Filter") {
  734. int i = 4;
  735. char vla[i];
  736. strcpy(vla, "{}");
  737. deserializeJson(doc, vla, NestingLimit(5), Filter(filter));
  738. }
  739. #endif
  740. }