unit-regression2.cpp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928
  1. // __ _____ _____ _____
  2. // __| | __| | | | JSON for Modern C++ (supporting code)
  3. // | | |__ | | | | | | version 3.11.2
  4. // |_____|_____|_____|_|___| https://github.com/nlohmann/json
  5. //
  6. // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
  7. // SPDX-License-Identifier: MIT
  8. // cmake/test.cmake selects the C++ standard versions with which to build a
  9. // unit test based on the presence of JSON_HAS_CPP_<VERSION> macros.
  10. // When using macros that are only defined for particular versions of the standard
  11. // (e.g., JSON_HAS_FILESYSTEM for C++17 and up), please mention the corresponding
  12. // version macro in a comment close by, like this:
  13. // JSON_HAS_CPP_<VERSION> (do not remove; see note at top of file)
  14. #include "doctest_compatibility.h"
  15. // for some reason including this after the json header leads to linker errors with VS 2017...
  16. #include <locale>
  17. #define JSON_TESTS_PRIVATE
  18. #include <nlohmann/json.hpp>
  19. using json = nlohmann::json;
  20. using ordered_json = nlohmann::ordered_json;
  21. #ifdef JSON_TEST_NO_GLOBAL_UDLS
  22. using namespace nlohmann::literals; // NOLINT(google-build-using-namespace)
  23. #endif
  24. #include <cstdio>
  25. #include <list>
  26. #include <type_traits>
  27. #include <utility>
  28. #ifdef JSON_HAS_CPP_17
  29. #include <any>
  30. #include <variant>
  31. #endif
  32. #ifdef JSON_HAS_CPP_20
  33. #include <span>
  34. #endif
  35. // NLOHMANN_JSON_SERIALIZE_ENUM uses a static std::pair
  36. DOCTEST_CLANG_SUPPRESS_WARNING_PUSH
  37. DOCTEST_CLANG_SUPPRESS_WARNING("-Wexit-time-destructors")
  38. /////////////////////////////////////////////////////////////////////
  39. // for #1021
  40. /////////////////////////////////////////////////////////////////////
  41. using float_json = nlohmann::basic_json<std::map, std::vector, std::string, bool, std::int64_t, std::uint64_t, float>;
  42. /////////////////////////////////////////////////////////////////////
  43. // for #1647
  44. /////////////////////////////////////////////////////////////////////
  45. namespace
  46. {
  47. struct NonDefaultFromJsonStruct
  48. {};
  49. inline bool operator==(NonDefaultFromJsonStruct const& /*unused*/, NonDefaultFromJsonStruct const& /*unused*/)
  50. {
  51. return true;
  52. }
  53. enum class for_1647
  54. {
  55. one,
  56. two
  57. };
  58. // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays): this is a false positive
  59. NLOHMANN_JSON_SERIALIZE_ENUM(for_1647,
  60. {
  61. {for_1647::one, "one"},
  62. {for_1647::two, "two"},
  63. })
  64. } // namespace
  65. /////////////////////////////////////////////////////////////////////
  66. // for #1299
  67. /////////////////////////////////////////////////////////////////////
  68. struct Data
  69. {
  70. Data() = default;
  71. Data(std::string a_, std::string b_)
  72. : a(std::move(a_))
  73. , b(std::move(b_))
  74. {}
  75. std::string a{};
  76. std::string b{};
  77. };
  78. void from_json(const json& j, Data& data);
  79. void from_json(const json& j, Data& data)
  80. {
  81. j["a"].get_to(data.a);
  82. j["b"].get_to(data.b);
  83. }
  84. bool operator==(Data const& lhs, Data const& rhs);
  85. bool operator==(Data const& lhs, Data const& rhs)
  86. {
  87. return lhs.a == rhs.a && lhs.b == rhs.b;
  88. }
  89. //bool operator!=(Data const& lhs, Data const& rhs)
  90. //{
  91. // return !(lhs == rhs);
  92. //}
  93. namespace nlohmann
  94. {
  95. template<>
  96. struct adl_serializer<NonDefaultFromJsonStruct>
  97. {
  98. static NonDefaultFromJsonStruct from_json(json const& /*unused*/) noexcept
  99. {
  100. return {};
  101. }
  102. };
  103. } // namespace nlohmann
  104. /////////////////////////////////////////////////////////////////////
  105. // for #1805
  106. /////////////////////////////////////////////////////////////////////
  107. struct NotSerializableData
  108. {
  109. int mydata;
  110. float myfloat;
  111. };
  112. /////////////////////////////////////////////////////////////////////
  113. // for #2574
  114. /////////////////////////////////////////////////////////////////////
  115. struct NonDefaultConstructible
  116. {
  117. explicit NonDefaultConstructible(int a)
  118. : x(a)
  119. {}
  120. int x;
  121. };
  122. namespace nlohmann
  123. {
  124. template<>
  125. struct adl_serializer<NonDefaultConstructible>
  126. {
  127. static NonDefaultConstructible from_json(json const& j)
  128. {
  129. return NonDefaultConstructible(j.get<int>());
  130. }
  131. };
  132. } // namespace nlohmann
  133. /////////////////////////////////////////////////////////////////////
  134. // for #2824
  135. /////////////////////////////////////////////////////////////////////
  136. class sax_no_exception : public nlohmann::detail::json_sax_dom_parser<json>
  137. {
  138. public:
  139. explicit sax_no_exception(json& j)
  140. : nlohmann::detail::json_sax_dom_parser<json>(j, false)
  141. {}
  142. static bool parse_error(std::size_t /*position*/, const std::string& /*last_token*/, const json::exception& ex)
  143. {
  144. error_string = new std::string(ex.what()); // NOLINT(cppcoreguidelines-owning-memory)
  145. return false;
  146. }
  147. static std::string* error_string;
  148. };
  149. std::string* sax_no_exception::error_string = nullptr;
  150. /////////////////////////////////////////////////////////////////////
  151. // for #2982
  152. /////////////////////////////////////////////////////////////////////
  153. template<class T>
  154. class my_allocator : public std::allocator<T>
  155. {
  156. public:
  157. using std::allocator<T>::allocator;
  158. };
  159. /////////////////////////////////////////////////////////////////////
  160. // for #3077
  161. /////////////////////////////////////////////////////////////////////
  162. class FooAlloc
  163. {};
  164. class Foo
  165. {
  166. public:
  167. explicit Foo(const FooAlloc& /* unused */ = FooAlloc()) {}
  168. bool value = false;
  169. };
  170. class FooBar
  171. {
  172. public:
  173. Foo foo{};
  174. };
  175. inline void from_json(const nlohmann::json& j, FooBar& fb)
  176. {
  177. j.at("value").get_to(fb.foo.value);
  178. }
  179. /////////////////////////////////////////////////////////////////////
  180. // for #3171
  181. /////////////////////////////////////////////////////////////////////
  182. struct for_3171_base // NOLINT(cppcoreguidelines-special-member-functions)
  183. {
  184. for_3171_base(const std::string& /*unused*/ = {}) {}
  185. virtual ~for_3171_base() = default;
  186. virtual void _from_json(const json& j)
  187. {
  188. j.at("str").get_to(str);
  189. }
  190. std::string str{};
  191. };
  192. struct for_3171_derived : public for_3171_base
  193. {
  194. for_3171_derived() = default;
  195. explicit for_3171_derived(const std::string& /*unused*/) { }
  196. };
  197. inline void from_json(const json& j, for_3171_base& tb)
  198. {
  199. tb._from_json(j);
  200. }
  201. /////////////////////////////////////////////////////////////////////
  202. // for #3312
  203. /////////////////////////////////////////////////////////////////////
  204. #ifdef JSON_HAS_CPP_20
  205. struct for_3312
  206. {
  207. std::string name;
  208. };
  209. inline void from_json(const json& j, for_3312& obj)
  210. {
  211. j.at("name").get_to(obj.name);
  212. }
  213. #endif
  214. /////////////////////////////////////////////////////////////////////
  215. // for #3204
  216. /////////////////////////////////////////////////////////////////////
  217. struct for_3204_foo
  218. {
  219. for_3204_foo() = default;
  220. explicit for_3204_foo(std::string /*unused*/) {} // NOLINT(performance-unnecessary-value-param)
  221. };
  222. struct for_3204_bar
  223. {
  224. enum constructed_from_t
  225. {
  226. constructed_from_none = 0,
  227. constructed_from_foo = 1,
  228. constructed_from_json = 2
  229. };
  230. explicit for_3204_bar(std::function<void(for_3204_foo)> /*unused*/) noexcept // NOLINT(performance-unnecessary-value-param)
  231. : constructed_from(constructed_from_foo) {}
  232. explicit for_3204_bar(std::function<void(json)> /*unused*/) noexcept // NOLINT(performance-unnecessary-value-param)
  233. : constructed_from(constructed_from_json) {}
  234. constructed_from_t constructed_from = constructed_from_none;
  235. };
  236. /////////////////////////////////////////////////////////////////////
  237. // for #3333
  238. /////////////////////////////////////////////////////////////////////
  239. struct for_3333 final
  240. {
  241. for_3333(int x_ = 0, int y_ = 0) : x(x_), y(y_) {}
  242. template <class T>
  243. for_3333(const T& /*unused*/)
  244. {
  245. CHECK(false);
  246. }
  247. int x = 0;
  248. int y = 0;
  249. };
  250. template <>
  251. inline for_3333::for_3333(const json& j)
  252. : for_3333(j.value("x", 0), j.value("y", 0))
  253. {}
  254. TEST_CASE("regression tests 2")
  255. {
  256. SECTION("issue #1001 - Fix memory leak during parser callback")
  257. {
  258. const auto* geojsonExample = R"(
  259. { "type": "FeatureCollection",
  260. "features": [
  261. { "type": "Feature",
  262. "geometry": {"type": "Point", "coordinates": [102.0, 0.5]},
  263. "properties": {"prop0": "value0"}
  264. },
  265. { "type": "Feature",
  266. "geometry": {
  267. "type": "LineString",
  268. "coordinates": [
  269. [102.0, 0.0], [103.0, 1.0], [104.0, 0.0], [105.0, 1.0]
  270. ]
  271. },
  272. "properties": {
  273. "prop0": "value0",
  274. "prop1": 0.0
  275. }
  276. },
  277. { "type": "Feature",
  278. "geometry": {
  279. "type": "Polygon",
  280. "coordinates": [
  281. [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0],
  282. [100.0, 1.0], [100.0, 0.0] ]
  283. ]
  284. },
  285. "properties": {
  286. "prop0": "value0",
  287. "prop1": {"this": "that"}
  288. }
  289. }
  290. ]
  291. })";
  292. const json::parser_callback_t cb = [&](int /*level*/, json::parse_event_t event, json & parsed) noexcept
  293. {
  294. // skip uninteresting events
  295. if (event == json::parse_event_t::value && !parsed.is_primitive())
  296. {
  297. return false;
  298. }
  299. switch (event)
  300. {
  301. case json::parse_event_t::key:
  302. {
  303. return true;
  304. }
  305. case json::parse_event_t::value:
  306. {
  307. return false;
  308. }
  309. case json::parse_event_t::object_start:
  310. {
  311. return true;
  312. }
  313. case json::parse_event_t::object_end:
  314. {
  315. return false;
  316. }
  317. case json::parse_event_t::array_start:
  318. {
  319. return true;
  320. }
  321. case json::parse_event_t::array_end:
  322. {
  323. return false;
  324. }
  325. default:
  326. {
  327. return true;
  328. }
  329. }
  330. };
  331. auto j = json::parse(geojsonExample, cb, true);
  332. CHECK(j == json());
  333. }
  334. SECTION("issue #1021 - to/from_msgpack only works with standard typization")
  335. {
  336. float_json j = 1000.0;
  337. CHECK(float_json::from_cbor(float_json::to_cbor(j)) == j);
  338. CHECK(float_json::from_msgpack(float_json::to_msgpack(j)) == j);
  339. CHECK(float_json::from_ubjson(float_json::to_ubjson(j)) == j);
  340. float_json j2 = {1000.0, 2000.0, 3000.0};
  341. CHECK(float_json::from_ubjson(float_json::to_ubjson(j2, true, true)) == j2);
  342. }
  343. SECTION("issue #1045 - Using STL algorithms with JSON containers with expected results?")
  344. {
  345. json diffs = nlohmann::json::array();
  346. json m1{{"key1", 42}};
  347. json m2{{"key2", 42}};
  348. auto p1 = m1.items();
  349. auto p2 = m2.items();
  350. using it_type = decltype(p1.begin());
  351. std::set_difference(
  352. p1.begin(),
  353. p1.end(),
  354. p2.begin(),
  355. p2.end(),
  356. std::inserter(diffs, diffs.end()),
  357. [&](const it_type & e1, const it_type & e2) -> bool
  358. {
  359. using comper_pair = std::pair<std::string, decltype(e1.value())>; // Trying to avoid unneeded copy
  360. return comper_pair(e1.key(), e1.value()) < comper_pair(e2.key(), e2.value()); // Using pair comper
  361. });
  362. CHECK(diffs.size() == 1); // Note the change here, was 2
  363. }
  364. #ifdef JSON_HAS_CPP_17
  365. SECTION("issue #1292 - Serializing std::variant causes stack overflow")
  366. {
  367. static_assert(!std::is_constructible<json, std::variant<int, float>>::value, "unexpected value");
  368. }
  369. #endif
  370. SECTION("issue #1299 - compile error in from_json converting to container "
  371. "with std::pair")
  372. {
  373. const json j =
  374. {
  375. {"1", {{"a", "testa_1"}, {"b", "testb_1"}}},
  376. {"2", {{"a", "testa_2"}, {"b", "testb_2"}}},
  377. {"3", {{"a", "testa_3"}, {"b", "testb_3"}}},
  378. };
  379. std::map<std::string, Data> expected
  380. {
  381. {"1", {"testa_1", "testb_1"}},
  382. {"2", {"testa_2", "testb_2"}},
  383. {"3", {"testa_3", "testb_3"}},
  384. };
  385. const auto data = j.get<decltype(expected)>();
  386. CHECK(expected == data);
  387. }
  388. SECTION("issue #1445 - buffer overflow in dumping invalid utf-8 strings")
  389. {
  390. SECTION("a bunch of -1, ensure_ascii=true")
  391. {
  392. const auto length = 300;
  393. json dump_test;
  394. dump_test["1"] = std::string(length, -1);
  395. std::string expected = R"({"1":")";
  396. for (int i = 0; i < length; ++i)
  397. {
  398. expected += "\\ufffd";
  399. }
  400. expected += "\"}";
  401. auto s = dump_test.dump(-1, ' ', true, nlohmann::json::error_handler_t::replace);
  402. CHECK(s == expected);
  403. }
  404. SECTION("a bunch of -2, ensure_ascii=false")
  405. {
  406. const auto length = 500;
  407. json dump_test;
  408. dump_test["1"] = std::string(length, -2);
  409. std::string expected = R"({"1":")";
  410. for (int i = 0; i < length; ++i)
  411. {
  412. expected += "\xEF\xBF\xBD";
  413. }
  414. expected += "\"}";
  415. auto s = dump_test.dump(-1, ' ', false, nlohmann::json::error_handler_t::replace);
  416. CHECK(s == expected);
  417. }
  418. SECTION("test case in issue #1445")
  419. {
  420. nlohmann::json dump_test;
  421. const std::array<int, 108> data =
  422. {
  423. {109, 108, 103, 125, -122, -53, 115, 18, 3, 0, 102, 19, 1, 15, -110, 13, -3, -1, -81, 32, 2, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -80, 2, 0, 0, 96, -118, 46, -116, 46, 109, -84, -87, 108, 14, 109, -24, -83, 13, -18, -51, -83, -52, -115, 14, 6, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 3, 0, 0, 0, 35, -74, -73, 55, 57, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, -96, -54, -28, -26}
  424. };
  425. std::string s;
  426. for (const int i : data)
  427. {
  428. s += static_cast<char>(i);
  429. }
  430. dump_test["1"] = s;
  431. dump_test.dump(-1, ' ', true, nlohmann::json::error_handler_t::replace);
  432. }
  433. }
  434. SECTION("issue #1447 - Integer Overflow (OSS-Fuzz 12506)")
  435. {
  436. const json j = json::parse("[-9223372036854775808]");
  437. CHECK(j.dump() == "[-9223372036854775808]");
  438. }
  439. SECTION("issue #1708 - minimum value of int64_t can be outputted")
  440. {
  441. constexpr auto smallest = (std::numeric_limits<int64_t>::min)();
  442. const json j = smallest;
  443. CHECK(j.dump() == std::to_string(smallest));
  444. }
  445. SECTION("issue #1727 - Contains with non-const lvalue json_pointer picks the wrong overload")
  446. {
  447. const json j = {{"root", {{"settings", {{"logging", true}}}}}};
  448. auto jptr1 = "/root/settings/logging"_json_pointer;
  449. auto jptr2 = json::json_pointer{"/root/settings/logging"};
  450. CHECK(j.contains(jptr1));
  451. CHECK(j.contains(jptr2));
  452. }
  453. SECTION("issue #1647 - compile error when deserializing enum if both non-default from_json and non-member operator== exists for other type")
  454. {
  455. // does not compile on ICPC when targeting C++20
  456. #if !(defined(__INTEL_COMPILER) && __cplusplus >= 202000)
  457. {
  458. const json j;
  459. NonDefaultFromJsonStruct x(j);
  460. NonDefaultFromJsonStruct y;
  461. CHECK(x == y);
  462. }
  463. #endif
  464. auto val = nlohmann::json("one").get<for_1647>();
  465. CHECK(val == for_1647::one);
  466. const json j = val;
  467. }
  468. SECTION("issue #1715 - json::from_cbor does not respect allow_exceptions = false when input is string literal")
  469. {
  470. SECTION("string literal")
  471. {
  472. const json cbor = json::from_cbor("B", true, false);
  473. CHECK(cbor.is_discarded());
  474. }
  475. SECTION("string array")
  476. {
  477. const std::array<char, 2> input = {{'B', 0x00}};
  478. const json cbor = json::from_cbor(input, true, false);
  479. CHECK(cbor.is_discarded());
  480. }
  481. SECTION("std::string")
  482. {
  483. const json cbor = json::from_cbor(std::string("B"), true, false);
  484. CHECK(cbor.is_discarded());
  485. }
  486. }
  487. SECTION("issue #1805 - A pair<T1, T2> is json constructible only if T1 and T2 are json constructible")
  488. {
  489. static_assert(!std::is_constructible<json, std::pair<std::string, NotSerializableData>>::value, "unexpected result");
  490. static_assert(!std::is_constructible<json, std::pair<NotSerializableData, std::string>>::value, "unexpected result");
  491. static_assert(std::is_constructible<json, std::pair<int, std::string>>::value, "unexpected result");
  492. }
  493. SECTION("issue #1825 - A tuple<Args..> is json constructible only if all T in Args are json constructible")
  494. {
  495. static_assert(!std::is_constructible<json, std::tuple<std::string, NotSerializableData>>::value, "unexpected result");
  496. static_assert(!std::is_constructible<json, std::tuple<NotSerializableData, std::string>>::value, "unexpected result");
  497. static_assert(std::is_constructible<json, std::tuple<int, std::string>>::value, "unexpected result");
  498. }
  499. SECTION("issue #1983 - JSON patch diff for op=add formation is not as per standard (RFC 6902)")
  500. {
  501. const auto source = R"({ "foo": [ "1", "2" ] })"_json;
  502. const auto target = R"({"foo": [ "1", "2", "3" ]})"_json;
  503. const auto result = json::diff(source, target);
  504. CHECK(result.dump() == R"([{"op":"add","path":"/foo/-","value":"3"}])");
  505. }
  506. SECTION("issue #2067 - cannot serialize binary data to text JSON")
  507. {
  508. const std::array<unsigned char, 23> data = {{0x81, 0xA4, 0x64, 0x61, 0x74, 0x61, 0xC4, 0x0F, 0x33, 0x30, 0x30, 0x32, 0x33, 0x34, 0x30, 0x31, 0x30, 0x37, 0x30, 0x35, 0x30, 0x31, 0x30}};
  509. const json j = json::from_msgpack(data.data(), data.size());
  510. CHECK_NOTHROW(
  511. j.dump(4, // Indent
  512. ' ', // Indent char
  513. false, // Ensure ascii
  514. json::error_handler_t::strict // Error
  515. ));
  516. }
  517. SECTION("PR #2181 - regression bug with lvalue")
  518. {
  519. // see https://github.com/nlohmann/json/pull/2181#issuecomment-653326060
  520. const json j{{"x", "test"}};
  521. const std::string defval = "default value";
  522. auto val = j.value("x", defval);
  523. auto val2 = j.value("y", defval);
  524. }
  525. SECTION("issue #2293 - eof doesn't cause parsing to stop")
  526. {
  527. const std::vector<uint8_t> data =
  528. {
  529. 0x7B,
  530. 0x6F,
  531. 0x62,
  532. 0x6A,
  533. 0x65,
  534. 0x63,
  535. 0x74,
  536. 0x20,
  537. 0x4F,
  538. 0x42
  539. };
  540. const json result = json::from_cbor(data, true, false);
  541. CHECK(result.is_discarded());
  542. }
  543. SECTION("issue #2315 - json.update and vector<pair>does not work with ordered_json")
  544. {
  545. nlohmann::ordered_json jsonAnimals = {{"animal", "dog"}};
  546. const nlohmann::ordered_json jsonCat = {{"animal", "cat"}};
  547. jsonAnimals.update(jsonCat);
  548. CHECK(jsonAnimals["animal"] == "cat");
  549. auto jsonAnimals_parsed = nlohmann::ordered_json::parse(jsonAnimals.dump());
  550. CHECK(jsonAnimals == jsonAnimals_parsed);
  551. const std::vector<std::pair<std::string, int64_t>> intData = {std::make_pair("aaaa", 11),
  552. std::make_pair("bbb", 222)
  553. };
  554. nlohmann::ordered_json jsonObj;
  555. for (const auto& data : intData)
  556. {
  557. jsonObj[data.first] = data.second;
  558. }
  559. CHECK(jsonObj["aaaa"] == 11);
  560. CHECK(jsonObj["bbb"] == 222);
  561. }
  562. SECTION("issue #2330 - ignore_comment=true fails on multiple consecutive lines starting with comments")
  563. {
  564. const std::string ss = "//\n//\n{\n}\n";
  565. const json j = json::parse(ss, nullptr, true, true);
  566. CHECK(j.dump() == "{}");
  567. }
  568. #ifdef JSON_HAS_CPP_20
  569. SECTION("issue #2546 - parsing containers of std::byte")
  570. {
  571. const char DATA[] = R"("Hello, world!")"; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
  572. const auto s = std::as_bytes(std::span(DATA));
  573. const json j = json::parse(s);
  574. CHECK(j.dump() == "\"Hello, world!\"");
  575. }
  576. #endif
  577. SECTION("issue #2574 - Deserialization to std::array, std::pair, and std::tuple with non-default constructable types fails")
  578. {
  579. SECTION("std::array")
  580. {
  581. {
  582. const json j = {7, 4};
  583. auto arr = j.get<std::array<NonDefaultConstructible, 2>>();
  584. CHECK(arr[0].x == 7);
  585. CHECK(arr[1].x == 4);
  586. }
  587. {
  588. const json j = 7;
  589. CHECK_THROWS_AS((j.get<std::array<NonDefaultConstructible, 1>>()), json::type_error);
  590. }
  591. }
  592. SECTION("std::pair")
  593. {
  594. {
  595. const json j = {3, 8};
  596. auto p = j.get<std::pair<NonDefaultConstructible, NonDefaultConstructible>>();
  597. CHECK(p.first.x == 3);
  598. CHECK(p.second.x == 8);
  599. }
  600. {
  601. const json j = {4, 1};
  602. auto p = j.get<std::pair<int, NonDefaultConstructible>>();
  603. CHECK(p.first == 4);
  604. CHECK(p.second.x == 1);
  605. }
  606. {
  607. const json j = {6, 7};
  608. auto p = j.get<std::pair<NonDefaultConstructible, int>>();
  609. CHECK(p.first.x == 6);
  610. CHECK(p.second == 7);
  611. }
  612. {
  613. const json j = 7;
  614. CHECK_THROWS_AS((j.get<std::pair<NonDefaultConstructible, int>>()), json::type_error);
  615. }
  616. }
  617. SECTION("std::tuple")
  618. {
  619. {
  620. const json j = {9};
  621. auto t = j.get<std::tuple<NonDefaultConstructible>>();
  622. CHECK(std::get<0>(t).x == 9);
  623. }
  624. {
  625. const json j = {9, 8, 7};
  626. auto t = j.get<std::tuple<NonDefaultConstructible, int, NonDefaultConstructible>>();
  627. CHECK(std::get<0>(t).x == 9);
  628. CHECK(std::get<1>(t) == 8);
  629. CHECK(std::get<2>(t).x == 7);
  630. }
  631. {
  632. const json j = 7;
  633. CHECK_THROWS_AS((j.get<std::tuple<NonDefaultConstructible>>()), json::type_error);
  634. }
  635. }
  636. }
  637. SECTION("issue #2865 - ASAN detects memory leaks")
  638. {
  639. // the code below is expected to not leak memory
  640. {
  641. nlohmann::json o;
  642. const std::string s = "bar";
  643. nlohmann::to_json(o["foo"], s);
  644. nlohmann::json p = o;
  645. // call to_json with a non-null JSON value
  646. nlohmann::to_json(p["foo"], s);
  647. }
  648. {
  649. nlohmann::json o;
  650. const std::string s = "bar";
  651. nlohmann::to_json(o["foo"], s);
  652. // call to_json with a non-null JSON value
  653. nlohmann::to_json(o["foo"], s);
  654. }
  655. }
  656. SECTION("issue #2824 - encoding of json::exception::what()")
  657. {
  658. json j;
  659. sax_no_exception sax(j);
  660. CHECK(!json::sax_parse("xyz", &sax));
  661. CHECK(*sax_no_exception::error_string == "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - invalid literal; last read: 'x'");
  662. delete sax_no_exception::error_string; // NOLINT(cppcoreguidelines-owning-memory)
  663. }
  664. SECTION("issue #2825 - Properly constrain the basic_json conversion operator")
  665. {
  666. static_assert(std::is_copy_assignable<nlohmann::ordered_json>::value, "ordered_json must be copy assignable");
  667. }
  668. SECTION("issue #2958 - Inserting in unordered json using a pointer retains the leading slash")
  669. {
  670. const std::string p = "/root";
  671. json test1;
  672. test1[json::json_pointer(p)] = json::object();
  673. CHECK(test1.dump() == "{\"root\":{}}");
  674. ordered_json test2;
  675. test2[ordered_json::json_pointer(p)] = json::object();
  676. CHECK(test2.dump() == "{\"root\":{}}");
  677. // json::json_pointer and ordered_json::json_pointer are the same type; behave as above
  678. ordered_json test3;
  679. test3[json::json_pointer(p)] = json::object();
  680. CHECK(std::is_same<json::json_pointer::string_t, ordered_json::json_pointer::string_t>::value);
  681. CHECK(test3.dump() == "{\"root\":{}}");
  682. }
  683. SECTION("issue #2982 - to_{binary format} does not provide a mechanism for specifying a custom allocator for the returned type")
  684. {
  685. std::vector<std::uint8_t, my_allocator<std::uint8_t>> my_vector;
  686. json j = {1, 2, 3, 4};
  687. json::to_cbor(j, my_vector);
  688. json k = json::from_cbor(my_vector);
  689. CHECK(j == k);
  690. }
  691. #if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
  692. // JSON_HAS_CPP_17 (do not remove; see note at top of file)
  693. SECTION("issue #3070 - Version 3.10.3 breaks backward-compatibility with 3.10.2 ")
  694. {
  695. nlohmann::detail::std_fs::path text_path("/tmp/text.txt");
  696. const json j(text_path);
  697. const auto j_path = j.get<nlohmann::detail::std_fs::path>();
  698. CHECK(j_path == text_path);
  699. #if DOCTEST_CLANG || DOCTEST_GCC >= DOCTEST_COMPILER(8, 4, 0)
  700. // only known to work on Clang and GCC >=8.4
  701. CHECK_THROWS_WITH_AS(nlohmann::detail::std_fs::path(json(1)), "[json.exception.type_error.302] type must be string, but is number", json::type_error);
  702. #endif
  703. }
  704. #endif
  705. SECTION("issue #3077 - explicit constructor with default does not compile")
  706. {
  707. json j;
  708. j[0]["value"] = true;
  709. std::vector<FooBar> foo;
  710. j.get_to(foo);
  711. }
  712. SECTION("issue #3108 - ordered_json doesn't support range based erase")
  713. {
  714. ordered_json j = {1, 2, 2, 4};
  715. auto last = std::unique(j.begin(), j.end());
  716. j.erase(last, j.end());
  717. CHECK(j.dump() == "[1,2,4]");
  718. j.erase(std::remove_if(j.begin(), j.end(), [](const ordered_json & val)
  719. {
  720. return val == 2;
  721. }), j.end());
  722. CHECK(j.dump() == "[1,4]");
  723. }
  724. SECTION("issue #3343 - json and ordered_json are not interchangable")
  725. {
  726. json::object_t jobj({ { "product", "one" } });
  727. ordered_json::object_t ojobj({{"product", "one"}});
  728. auto jit = jobj.begin();
  729. auto ojit = ojobj.begin();
  730. CHECK(jit->first == ojit->first);
  731. CHECK(jit->second.get<std::string>() == ojit->second.get<std::string>());
  732. }
  733. SECTION("issue #3171 - if class is_constructible from std::string wrong from_json overload is being selected, compilation failed")
  734. {
  735. const json j{{ "str", "value"}};
  736. // failed with: error: no match for ‘operator=’ (operand types are ‘for_3171_derived’ and ‘const nlohmann::basic_json<>::string_t’
  737. // {aka ‘const std::__cxx11::basic_string<char>’})
  738. // s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
  739. auto td = j.get<for_3171_derived>();
  740. CHECK(td.str == "value");
  741. }
  742. #ifdef JSON_HAS_CPP_20
  743. SECTION("issue #3312 - Parse to custom class from unordered_json breaks on G++11.2.0 with C++20")
  744. {
  745. // see test for #3171
  746. const ordered_json j = {{"name", "class"}};
  747. for_3312 obj{};
  748. j.get_to(obj);
  749. CHECK(obj.name == "class");
  750. }
  751. #endif
  752. #if defined(JSON_HAS_CPP_17) && JSON_USE_IMPLICIT_CONVERSIONS
  753. SECTION("issue #3428 - Error occurred when converting nlohmann::json to std::any")
  754. {
  755. const json j;
  756. const std::any a1 = j;
  757. std::any&& a2 = j;
  758. CHECK(a1.type() == typeid(j));
  759. CHECK(a2.type() == typeid(j));
  760. }
  761. #endif
  762. SECTION("issue #3204 - ambiguous regression")
  763. {
  764. for_3204_bar bar_from_foo([](for_3204_foo) noexcept {}); // NOLINT(performance-unnecessary-value-param)
  765. for_3204_bar bar_from_json([](json) noexcept {}); // NOLINT(performance-unnecessary-value-param)
  766. CHECK(bar_from_foo.constructed_from == for_3204_bar::constructed_from_foo);
  767. CHECK(bar_from_json.constructed_from == for_3204_bar::constructed_from_json);
  768. }
  769. SECTION("issue #3333 - Ambiguous conversion from nlohmann::basic_json<> to custom class")
  770. {
  771. const json j
  772. {
  773. {"x", 1},
  774. {"y", 2}
  775. };
  776. for_3333 p = j;
  777. CHECK(p.x == 1);
  778. CHECK(p.y == 2);
  779. }
  780. }
  781. DOCTEST_CLANG_SUPPRESS_WARNING_POP