1 /*
2 __ _____ _____ _____
3 __| | __| | | | JSON for Modern C++ (test suite)
4 | | |__ | | | | | | version 3.7.3
5 |_____|_____|_____|_|___| https://github.com/nlohmann/json
6
7 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
8 SPDX-License-Identifier: MIT
9 Copyright (c) 2013-2019 Niels Lohmann <http://nlohmann.me>.
10
11 Permission is hereby granted, free of charge, to any person obtaining a copy
12 of this software and associated documentation files (the "Software"), to deal
13 in the Software without restriction, including without limitation the rights
14 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 copies of the Software, and to permit persons to whom the Software is
16 furnished to do so, subject to the following conditions:
17
18 The above copyright notice and this permission notice shall be included in all
19 copies or substantial portions of the Software.
20
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 SOFTWARE.
28 */
29
30 #include "doctest_compatibility.h"
31 DOCTEST_GCC_SUPPRESS_WARNING("-Wfloat-equal")
32
33 // for some reason including this after the json header leads to linker errors with VS 2017...
34 #include <locale>
35
36 #define private public
37 #include <nlohmann/json.hpp>
38 using nlohmann::json;
39 #undef private
40
41 #include <fstream>
42 #include <sstream>
43 #include <list>
44 #include <cstdio>
45
46 #if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
47 #define JSON_HAS_CPP_17
48 #endif
49
50 #ifdef JSON_HAS_CPP_17
51 #include <variant>
52 #endif
53
54 #include "fifo_map.hpp"
55
56 /////////////////////////////////////////////////////////////////////
57 // for #972
58 /////////////////////////////////////////////////////////////////////
59
60 template<class K, class V, class dummy_compare, class A>
61 using my_workaround_fifo_map = nlohmann::fifo_map<K, V, nlohmann::fifo_map_compare<K>, A>;
62 using my_json = nlohmann::basic_json<my_workaround_fifo_map>;
63
64 /////////////////////////////////////////////////////////////////////
65 // for #977
66 /////////////////////////////////////////////////////////////////////
67
68 namespace ns
69 {
70 struct foo
71 {
72 int x;
73 };
74
75 template <typename, typename SFINAE = void>
76 struct foo_serializer;
77
78 template<typename T>
79 struct foo_serializer<T, typename std::enable_if<std::is_same<foo, T>::value>::type>
80 {
81 template <typename BasicJsonType>
to_jsonns::foo_serializer82 static void to_json(BasicJsonType& j, const T& value)
83 {
84 j = BasicJsonType{{"x", value.x}};
85 }
86 template <typename BasicJsonType>
from_jsonns::foo_serializer87 static void from_json(const BasicJsonType& j, T& value) // !!!
88 {
89 nlohmann::from_json(j.at("x"), value.x);
90 }
91 };
92
93 template<typename T>
94 struct foo_serializer < T, typename std::enable_if < !std::is_same<foo, T>::value >::type >
95 {
96 template <typename BasicJsonType>
to_jsonns::foo_serializer97 static void to_json(BasicJsonType& j, const T& value) noexcept
98 {
99 ::nlohmann::to_json(j, value);
100 }
101 template <typename BasicJsonType>
from_jsonns::foo_serializer102 static void from_json(const BasicJsonType& j, T& value) //!!!
103 {
104 ::nlohmann::from_json(j, value);
105 }
106 };
107 }
108
109 using foo_json = nlohmann::basic_json<std::map, std::vector, std::string, bool, std::int64_t,
110 std::uint64_t, double, std::allocator, ns::foo_serializer>;
111
112 /////////////////////////////////////////////////////////////////////
113 // for #805
114 /////////////////////////////////////////////////////////////////////
115
116 namespace
117 {
118 struct nocopy
119 {
120 nocopy() = default;
121 nocopy(const nocopy&) = delete;
122
123 int val = 0;
124
to_json(json & j,const nocopy & n)125 friend void to_json(json& j, const nocopy& n)
126 {
127 j = {{"val", n.val}};
128 }
129 };
130
131 struct Data
132 {
133 Data() = default;
Data__anon9ae719c70111::Data134 Data(const std::string& a_, const std::string b_) : a(a_), b(b_) {}
135 std::string a {};
136 std::string b {};
137 };
138
from_json(const json & j,Data & data)139 void from_json(const json& j, Data& data)
140 {
141 j["a"].get_to(data.a);
142 j["b"].get_to(data.b);
143 }
144
operator ==(Data const & lhs,Data const & rhs)145 bool operator==(Data const& lhs, Data const& rhs)
146 {
147 return lhs.a == rhs.a && lhs.b == rhs.b;
148 }
149
150 //bool operator!=(Data const& lhs, Data const& rhs)
151 //{
152 // return !(lhs == rhs);
153 //}
154 }
155
156 /////////////////////////////////////////////////////////////////////
157 // for #1021
158 /////////////////////////////////////////////////////////////////////
159
160 using float_json = nlohmann::basic_json<std::map, std::vector, std::string, bool, std::int64_t, std::uint64_t, float>;
161
162 /////////////////////////////////////////////////////////////////////
163 // for #1647
164 /////////////////////////////////////////////////////////////////////
165 namespace
166 {
167 struct NonDefaultFromJsonStruct { };
168
operator ==(NonDefaultFromJsonStruct const &,NonDefaultFromJsonStruct const &)169 inline bool operator== (NonDefaultFromJsonStruct const&, NonDefaultFromJsonStruct const&)
170 {
171 return true;
172 }
173
174 enum class for_1647 { one, two };
175
176 NLOHMANN_JSON_SERIALIZE_ENUM(for_1647,
177 {
178 {for_1647::one, "one"},
179 {for_1647::two, "two"},
180 })
181 }
182
183 namespace nlohmann
184 {
185 template <>
186 struct adl_serializer<NonDefaultFromJsonStruct>
187 {
from_jsonnlohmann::adl_serializer188 static NonDefaultFromJsonStruct from_json (json const&) noexcept
189 {
190 return {};
191 }
192 };
193 }
194
195 /////////////////////////////////////////////////////////////////////
196 // for #1805
197 /////////////////////////////////////////////////////////////////////
198
199 struct NotSerializableData
200 {
201 int mydata;
202 float myfloat;
203 };
204
205
206 TEST_CASE("regression tests")
207 {
208 SECTION("issue #60 - Double quotation mark is not parsed correctly")
209 {
210 SECTION("escape_doublequote")
211 {
212 auto s = "[\"\\\"foo\\\"\"]";
213 json j = json::parse(s);
214 auto expected = R"(["\"foo\""])"_json;
215 CHECK(j == expected);
216 }
217 }
218
219 SECTION("issue #70 - Handle infinity and NaN cases")
220 {
221 // previously, NAN/INFINITY created a null value; now, the values are
222 // properly stored, but are dumped as "null"
223 SECTION("NAN value")
224 {
225 CHECK(json(NAN).dump() == "null");
226 CHECK(json(json::number_float_t(NAN)).dump() == "null");
227 }
228
229 SECTION("infinity")
230 {
231 CHECK(json(INFINITY).dump() == "null");
232 CHECK(json(json::number_float_t(INFINITY)).dump() == "null");
233 }
234
235 // With 3.0.0, the semantics of this changed: NAN and infinity are
236 // stored properly inside the JSON value (no exception or conversion
237 // to null), but are serialized as null.
238 SECTION("NAN value")
239 {
240 json j1 = NAN;
241 CHECK(j1.is_number_float());
242 json::number_float_t f1 = j1;
243 CHECK(std::isnan(f1));
244
245 json j2 = json::number_float_t(NAN);
246 CHECK(j2.is_number_float());
247 json::number_float_t f2 = j2;
248 CHECK(std::isnan(f2));
249 }
250
251 SECTION("infinity")
252 {
253 json j1 = INFINITY;
254 CHECK(j1.is_number_float());
255 json::number_float_t f1 = j1;
256 CHECK(not std::isfinite(f1));
257
258 json j2 = json::number_float_t(INFINITY);
259 CHECK(j2.is_number_float());
260 json::number_float_t f2 = j2;
261 CHECK(not std::isfinite(f2));
262 }
263 }
264
265 SECTION("pull request #71 - handle enum type")
266 {
267 enum { t = 0, u = 102};
268 json j = json::array();
269 j.push_back(t);
270
271 // maybe this is not the place to test this?
272 json j2 = u;
273
274 auto anon_enum_value = j2.get<decltype(u)>();
275 CHECK(u == anon_enum_value);
276
277 // check if the actual value was stored
278 CHECK(j2 == 102);
279
280 static_assert(std::is_same<decltype(anon_enum_value), decltype(u)>::value, "");
281
282 j.push_back(json::object(
283 {
284 {"game_type", t}
285 }));
286 }
287
288 SECTION("issue #76 - dump() / parse() not idempotent")
289 {
290 // create JSON object
291 json fields;
292 fields["one"] = std::string("one");
293 fields["two"] = std::string("two three");
294 fields["three"] = std::string("three \"four\"");
295
296 // create another JSON object by deserializing the serialization
297 std::string payload = fields.dump();
298 json parsed_fields = json::parse(payload);
299
300 // check individual fields to match both objects
301 CHECK(parsed_fields["one"] == fields["one"]);
302 CHECK(parsed_fields["two"] == fields["two"]);
303 CHECK(parsed_fields["three"] == fields["three"]);
304
305 // check individual fields to match original input
306 CHECK(parsed_fields["one"] == std::string("one"));
307 CHECK(parsed_fields["two"] == std::string("two three"));
308 CHECK(parsed_fields["three"] == std::string("three \"four\""));
309
310 // check equality of the objects
311 CHECK(parsed_fields == fields);
312
313 // check equality of the serialized objects
314 CHECK(fields.dump() == parsed_fields.dump());
315
316 // check everything in one line
317 CHECK(fields == json::parse(fields.dump()));
318 }
319
320 SECTION("issue #82 - lexer::get_number return NAN")
321 {
322 const auto content = R"(
323 {
324 "Test":"Test1",
325 "Number":100,
326 "Foo":42.42
327 })";
328
329 std::stringstream ss;
330 ss << content;
331 json j;
332 ss >> j;
333
334 std::string test = j["Test"];
335 CHECK(test == "Test1");
336 int number = j["Number"];
337 CHECK(number == 100);
338 float foo = j["Foo"];
339 CHECK(static_cast<double>(foo) == Approx(42.42));
340 }
341
342 SECTION("issue #89 - nonstandard integer type")
343 {
344 // create JSON class with nonstandard integer number type
345 using custom_json =
346 nlohmann::basic_json<std::map, std::vector, std::string, bool, int32_t, uint32_t, float>;
347 custom_json j;
348 j["int_1"] = 1;
349 CHECK(j["int_1"] == 1);
350
351 // tests for correct handling of non-standard integers that overflow the type selected by the user
352
353 // unsigned integer object creation - expected to wrap and still be stored as an integer
354 j = 4294967296U; // 2^32
355 CHECK(static_cast<int>(j.type()) == static_cast<int>(custom_json::value_t::number_unsigned));
356 CHECK(j.get<uint32_t>() == 0); // Wrap
357
358 // unsigned integer parsing - expected to overflow and be stored as a float
359 j = custom_json::parse("4294967296"); // 2^32
360 CHECK(static_cast<int>(j.type()) == static_cast<int>(custom_json::value_t::number_float));
361 CHECK(j.get<float>() == 4294967296.0f);
362
363 // integer object creation - expected to wrap and still be stored as an integer
364 j = -2147483649LL; // -2^31-1
365 CHECK(static_cast<int>(j.type()) == static_cast<int>(custom_json::value_t::number_integer));
366 CHECK(j.get<int32_t>() == 2147483647); // Wrap
367
368 // integer parsing - expected to overflow and be stored as a float with rounding
369 j = custom_json::parse("-2147483649"); // -2^31
370 CHECK(static_cast<int>(j.type()) == static_cast<int>(custom_json::value_t::number_float));
371 CHECK(j.get<float>() == -2147483650.0f);
372 }
373
374 SECTION("issue #93 reverse_iterator operator inheritance problem")
375 {
376 {
377 json a = {1, 2, 3};
378 json::reverse_iterator rit = a.rbegin();
379 ++rit;
380 CHECK(*rit == json(2));
381 CHECK(rit.value() == json(2));
382 }
383 {
384 json a = {1, 2, 3};
385 json::reverse_iterator rit = ++a.rbegin();
386 CHECK(*rit == json(2));
387 CHECK(rit.value() == json(2));
388 }
389 {
390 json a = {1, 2, 3};
391 json::reverse_iterator rit = a.rbegin();
392 ++rit;
393 json b = {0, 0, 0};
394 std::transform(rit, a.rend(), b.rbegin(), [](json el)
__anon9ae719c70402(json el) 395 {
396 return el;
397 });
398 CHECK(b == json({0, 1, 2}));
399 }
400 {
401 json a = {1, 2, 3};
402 json b = {0, 0, 0};
403 std::transform(++a.rbegin(), a.rend(), b.rbegin(), [](json el)
__anon9ae719c70502(json el) 404 {
405 return el;
406 });
407 CHECK(b == json({0, 1, 2}));
408 }
409 }
410
411 SECTION("issue #100 - failed to iterator json object with reverse_iterator")
412 {
413 json config =
414 {
415 { "111", 111 },
416 { "112", 112 },
417 { "113", 113 }
418 };
419
420 std::stringstream ss;
421
422 for (auto it = config.begin(); it != config.end(); ++it)
423 {
424 ss << it.key() << ": " << it.value() << '\n';
425 }
426
427 for (auto it = config.rbegin(); it != config.rend(); ++it)
428 {
429 ss << it.key() << ": " << it.value() << '\n';
430 }
431
432 CHECK(ss.str() == "111: 111\n112: 112\n113: 113\n113: 113\n112: 112\n111: 111\n");
433 }
434
435 SECTION("issue #101 - binary string causes numbers to be dumped as hex")
436 {
437 int64_t number = 10;
438 std::string bytes{"\x00" "asdf\n", 6};
439 json j;
440 j["int64"] = number;
441 j["binary string"] = bytes;
442 // make sure the number is really printed as decimal "10" and not as
443 // hexadecimal "a"
444 CHECK(j.dump() == "{\"binary string\":\"\\u0000asdf\\n\",\"int64\":10}");
445 }
446
447 SECTION("issue #111 - subsequent unicode chars")
448 {
449 std::string bytes{0x7, 0x7};
450 json j;
451 j["string"] = bytes;
452 CHECK(j["string"] == "\u0007\u0007");
453 }
454
455 SECTION("issue #144 - implicit assignment to std::string fails")
456 {
457 json o = {{"name", "value"}};
458
459 std::string s1 = o["name"];
460 CHECK(s1 == "value");
461
462 std::string s2;
463 s2 = o["name"];
464
465 CHECK(s2 == "value");
466 }
467
468 SECTION("issue #146 - character following a surrogate pair is skipped")
469 {
470 CHECK(json::parse("\"\\ud80c\\udc60abc\"").get<json::string_t>() == u8"\U00013060abc");
471 }
472
473 SECTION("issue #171 - Cannot index by key of type static constexpr const char*")
474 {
475 json j;
476
477 // Non-const access with key as "char []"
478 char array_key[] = "Key1";
479 CHECK_NOTHROW(j[array_key] = 1);
480 CHECK(j[array_key] == json(1));
481
482 // Non-const access with key as "const char[]"
483 const char const_array_key[] = "Key2";
484 CHECK_NOTHROW(j[const_array_key] = 2);
485 CHECK(j[const_array_key] == json(2));
486
487 // Non-const access with key as "char *"
488 char _ptr_key[] = "Key3";
489 char* ptr_key = &_ptr_key[0];
490 CHECK_NOTHROW(j[ptr_key] = 3);
491 CHECK(j[ptr_key] == json(3));
492
493 // Non-const access with key as "const char *"
494 const char* const_ptr_key = "Key4";
495 CHECK_NOTHROW(j[const_ptr_key] = 4);
496 CHECK(j[const_ptr_key] == json(4));
497
498 // Non-const access with key as "static constexpr const char *"
499 static constexpr const char* constexpr_ptr_key = "Key5";
500 CHECK_NOTHROW(j[constexpr_ptr_key] = 5);
501 CHECK(j[constexpr_ptr_key] == json(5));
502
503 const json j_const = j;
504
505 // Const access with key as "char []"
506 CHECK(j_const[array_key] == json(1));
507
508 // Const access with key as "const char[]"
509 CHECK(j_const[const_array_key] == json(2));
510
511 // Const access with key as "char *"
512 CHECK(j_const[ptr_key] == json(3));
513
514 // Const access with key as "const char *"
515 CHECK(j_const[const_ptr_key] == json(4));
516
517 // Const access with key as "static constexpr const char *"
518 CHECK(j_const[constexpr_ptr_key] == json(5));
519 }
520
521 SECTION("issue #186 miloyip/nativejson-benchmark: floating-point parsing")
522 {
523 json j;
524
525 j = json::parse("-0.0");
526 CHECK(j.get<double>() == -0.0);
527
528 j = json::parse("2.22507385850720113605740979670913197593481954635164564e-308");
529 CHECK(j.get<double>() == 2.2250738585072009e-308);
530
531 j = json::parse("0.999999999999999944488848768742172978818416595458984374");
532 CHECK(j.get<double>() == 0.99999999999999989);
533
534 j = json::parse("1.00000000000000011102230246251565404236316680908203126");
535 CHECK(j.get<double>() == 1.00000000000000022);
536
537 j = json::parse("7205759403792793199999e-5");
538 CHECK(j.get<double>() == 72057594037927928.0);
539
540 j = json::parse("922337203685477529599999e-5");
541 CHECK(j.get<double>() == 9223372036854774784.0);
542
543 j = json::parse("1014120480182583464902367222169599999e-5");
544 CHECK(j.get<double>() == 10141204801825834086073718800384.0);
545
546 j = json::parse("5708990770823839207320493820740630171355185151999e-3");
547 CHECK(j.get<double>() == 5708990770823838890407843763683279797179383808.0);
548
549 // create JSON class with nonstandard float number type
550
551 // float
552 nlohmann::basic_json<std::map, std::vector, std::string, bool, int32_t, uint32_t, float> j_float =
553 1.23e25f;
554 CHECK(j_float.get<float>() == 1.23e25f);
555
556 // double
557 nlohmann::basic_json<std::map, std::vector, std::string, bool, int64_t, uint64_t, double> j_double =
558 1.23e35;
559 CHECK(j_double.get<double>() == 1.23e35);
560
561 // long double
562 nlohmann::basic_json<std::map, std::vector, std::string, bool, int64_t, uint64_t, long double>
563 j_long_double = 1.23e45L;
564 CHECK(j_long_double.get<long double>() == 1.23e45L);
565 }
566
567 SECTION("issue #228 - double values are serialized with commas as decimal points")
568 {
569 json j1a = 2312.42;
570 json j1b = json::parse("2312.42");
571
572 json j2a = 2342e-2;
573 //issue #230
574 //json j2b = json::parse("2342e-2");
575
576 json j3a = 10E3;
577 json j3b = json::parse("10E3");
578 json j3c = json::parse("10e3");
579
580 // class to create a locale that would use a comma for decimals
581 class CommaDecimalSeparator : public std::numpunct<char>
582 {
583 protected:
do_decimal_point() const584 char do_decimal_point() const override
585 {
586 return ',';
587 }
588
do_thousands_sep() const589 char do_thousands_sep() const override
590 {
591 return '.';
592 }
593
do_grouping() const594 std::string do_grouping() const override
595 {
596 return "\03";
597 }
598 };
599
600 // change locale to mess with decimal points
601 auto orig_locale = std::locale::global(std::locale(std::locale(), new CommaDecimalSeparator));
602
603 CHECK(j1a.dump() == "2312.42");
604 CHECK(j1b.dump() == "2312.42");
605
606 // check if locale is properly reset
607 std::stringstream ss;
608 ss.imbue(std::locale(std::locale(), new CommaDecimalSeparator));
609 ss << 4712.11;
610 CHECK(ss.str() == "4.712,11");
611 ss << j1a;
612 CHECK(ss.str() == "4.712,112312.42");
613 ss << 47.11;
614 CHECK(ss.str() == "4.712,112312.4247,11");
615
616 CHECK(j2a.dump() == "23.42");
617 //issue #230
618 //CHECK(j2b.dump() == "23.42");
619
620 CHECK(j3a.dump() == "10000.0");
621 CHECK(j3b.dump() == "10000.0");
622 CHECK(j3c.dump() == "10000.0");
623 //CHECK(j3b.dump() == "1E04"); // roundtrip error
624 //CHECK(j3c.dump() == "1e04"); // roundtrip error
625
626 std::locale::global(orig_locale);
627 }
628
629 SECTION("issue #378 - locale-independent num-to-str")
630 {
631 setlocale(LC_NUMERIC, "de_DE.UTF-8");
632
633 // verify that dumped correctly with '.' and no grouping
634 const json j1 = 12345.67;
635 CHECK(json(12345.67).dump() == "12345.67");
636 setlocale(LC_NUMERIC, "C");
637 }
638
639 SECTION("issue #379 - locale-independent str-to-num")
640 {
641 setlocale(LC_NUMERIC, "de_DE.UTF-8");
642
643 // verify that parsed correctly despite using strtod internally
644 CHECK(json::parse("3.14").get<double>() == 3.14);
645
646 // check a different code path
647 CHECK(json::parse("1.000000000000000000000000000000000000000000000000000000000000000000000000").get<double>() == 1.0);
648 }
649
650 SECTION("issue #233 - Can't use basic_json::iterator as a base iterator for std::move_iterator")
651 {
652 json source = {"a", "b", "c"};
653 json expected = {"a", "b"};
654 json dest;
655
656 std::copy_n(std::make_move_iterator(source.begin()), 2, std::back_inserter(dest));
657
658 CHECK(dest == expected);
659 }
660
661 SECTION("issue #235 - ambiguous overload for 'push_back' and 'operator+='")
662 {
663 json data = {{"key", "value"}};
664 data.push_back({"key2", "value2"});
665 data += {"key3", "value3"};
666
667 CHECK(data == json({{"key", "value"}, {"key2", "value2"}, {"key3", "value3"}}));
668 }
669
670 SECTION("issue #269 - diff generates incorrect patch when removing multiple array elements")
671 {
672 json doc = R"( { "arr1": [1, 2, 3, 4] } )"_json;
673 json expected = R"( { "arr1": [1, 2] } )"_json;
674
675 // check roundtrip
676 CHECK(doc.patch(json::diff(doc, expected)) == expected);
677 }
678
679 SECTION("issue #283 - value() does not work with _json_pointer types")
680 {
681 json j =
682 {
683 {"object", {{"key1", 1}, {"key2", 2}}},
684 };
685
686 int at_integer = j.at("/object/key2"_json_pointer);
687 int val_integer = j.value("/object/key2"_json_pointer, 0);
688
689 CHECK(at_integer == val_integer);
690 }
691
692 SECTION("issue #304 - Unused variable warning")
693 {
694 // code triggered a "warning: unused variable" warning and is left
695 // here to avoid the warning in the future
696 json object;
697 json patch = json::array();
698 object = object.patch(patch);
699 }
700
701 SECTION("issue #306 - Parsing fails without space at end of file")
702 {
703 for (auto filename :
704 {
705 "test/data/regression/broken_file.json",
706 "test/data/regression/working_file.json"
707 })
708 {
709 CAPTURE(filename)
710 json j;
711 std::ifstream f(filename);
712 CHECK_NOTHROW(f >> j);
713 }
714 }
715
716 SECTION("issue #310 - make json_benchmarks no longer working in 2.0.4")
717 {
718 for (auto filename :
719 {
720 "test/data/regression/floats.json",
721 "test/data/regression/signed_ints.json",
722 "test/data/regression/unsigned_ints.json",
723 "test/data/regression/small_signed_ints.json"
724 })
725 {
726 CAPTURE(filename)
727 json j;
728 std::ifstream f(filename);
729 CHECK_NOTHROW(f >> j);
730 }
731 }
732
733 SECTION("issue #323 - add nested object capabilities to pointers")
734 {
735 json j;
736 j["/this/that/2"_json_pointer] = 27;
737 CHECK(j == json({{"this", {{"that", {nullptr, nullptr, 27}}}}}));
738 }
739
740 SECTION("issue #329 - serialized value not always can be parsed")
741 {
742 json _;
743 CHECK_THROWS_AS(_ = json::parse("22e2222"), json::out_of_range&);
744 CHECK_THROWS_WITH(_ = json::parse("22e2222"),
745 "[json.exception.out_of_range.406] number overflow parsing '22e2222'");
746 }
747
748 SECTION("issue #360 - Loss of precision when serializing <double>")
749 {
750 auto check_roundtrip = [](double number)
__anon9ae719c70602(double number) 751 {
752 CAPTURE(number)
753
754 json j = number;
755 CHECK(j.is_number_float());
756
757 std::stringstream ss;
758 ss << j;
759
760 CHECK_NOTHROW(ss >> j);
761 CHECK(j.is_number_float());
762 CHECK(j.get<json::number_float_t>() == number);
763 };
764
765 check_roundtrip(100000000000.1236);
766 check_roundtrip((std::numeric_limits<json::number_float_t>::max)());
767
768 // Some more numbers which fail to roundtrip when serialized with digits10 significand digits (instead of max_digits10)
769 check_roundtrip(1.541888611948064e-17);
770 check_roundtrip(5.418771028591015e-16);
771 check_roundtrip(9.398685592608595e-15);
772 check_roundtrip(8.826843952762347e-14);
773 check_roundtrip(8.143291313475335e-13);
774 check_roundtrip(4.851328172762508e-12);
775 check_roundtrip(6.677850998084358e-11);
776 check_roundtrip(3.995398518174525e-10);
777 check_roundtrip(1.960452605645124e-9);
778 check_roundtrip(3.551812586302883e-8);
779 check_roundtrip(2.947988411689261e-7);
780 check_roundtrip(8.210166748056192e-6);
781 check_roundtrip(6.104889704266753e-5);
782 check_roundtrip(0.0008629954631330876);
783 check_roundtrip(0.004936993881051611);
784 check_roundtrip(0.08309725102608073);
785 check_roundtrip(0.5210494268499783);
786 check_roundtrip(6.382927930939767);
787 check_roundtrip(59.94947245358671);
788 check_roundtrip(361.0838651266122);
789 check_roundtrip(4678.354596181877);
790 check_roundtrip(61412.17658956043);
791 check_roundtrip(725696.0799057782);
792 check_roundtrip(2811732.583399828);
793 check_roundtrip(30178351.07533605);
794 check_roundtrip(689684880.3235844);
795 check_roundtrip(5714887673.555147);
796 check_roundtrip(84652038821.18808);
797 check_roundtrip(156510583431.7721);
798 check_roundtrip(5938450569021.732);
799 check_roundtrip(83623297654460.33);
800 check_roundtrip(701466573254773.6);
801 check_roundtrip(1369013370304513);
802 check_roundtrip(96963648023094720);
803 check_roundtrip(3.478237409280108e+17);
804 }
805
806 SECTION("issue #366 - json::parse on failed stream gets stuck")
807 {
808 std::ifstream f("file_not_found.json");
809 json _;
810 CHECK_THROWS_AS(_ = json::parse(f), json::parse_error&);
811 CHECK_THROWS_WITH(_ = json::parse(f), "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal");
812 }
813
814 SECTION("issue #367 - calling stream at EOF")
815 {
816 std::stringstream ss;
817 json j;
818 ss << "123";
819 CHECK_NOTHROW(ss >> j);
820
821 // see https://github.com/nlohmann/json/issues/367#issuecomment-262841893:
822 // ss is not at EOF; this yielded an error before the fix
823 // (threw basic_string::append). No, it should just throw
824 // a parse error because of the EOF.
825 CHECK_THROWS_AS(ss >> j, json::parse_error&);
826 CHECK_THROWS_WITH(ss >> j,
827 "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal");
828 }
829
830 SECTION("issue #367 - behavior of operator>> should more closely resemble that of built-in overloads")
831 {
832 SECTION("(empty)")
833 {
834 std::stringstream ss;
835 json j;
836 CHECK_THROWS_AS(ss >> j, json::parse_error&);
837 CHECK_THROWS_WITH(ss >> j,
838 "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal");
839 }
840
841 SECTION("(whitespace)")
842 {
843 std::stringstream ss;
844 ss << " ";
845 json j;
846 CHECK_THROWS_AS(ss >> j, json::parse_error&);
847 CHECK_THROWS_WITH(ss >> j,
848 "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal");
849 }
850
851 SECTION("one value")
852 {
853 std::stringstream ss;
854 ss << "111";
855 json j;
856 CHECK_NOTHROW(ss >> j);
857 CHECK(j == 111);
858
859 CHECK_THROWS_AS(ss >> j, json::parse_error&);
860 CHECK_THROWS_WITH(ss >> j,
861 "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal");
862 }
863
864 SECTION("one value + whitespace")
865 {
866 std::stringstream ss;
867 ss << "222 \t\n";
868 json j;
869 CHECK_NOTHROW(ss >> j);
870 CHECK(j == 222);
871
872 CHECK_THROWS_AS(ss >> j, json::parse_error&);
873 CHECK_THROWS_WITH(ss >> j,
874 "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal");
875 }
876
877 SECTION("whitespace + one value")
878 {
879 std::stringstream ss;
880 ss << "\n\t 333";
881 json j;
882 CHECK_NOTHROW(ss >> j);
883 CHECK(j == 333);
884
885 CHECK_THROWS_AS(ss >> j, json::parse_error&);
886 CHECK_THROWS_WITH(ss >> j,
887 "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal");
888 }
889
890 SECTION("three values")
891 {
892 std::stringstream ss;
893 ss << " 111 \n222\n \n 333";
894 json j;
895 CHECK_NOTHROW(ss >> j);
896 CHECK(j == 111);
897 CHECK_NOTHROW(ss >> j);
898 CHECK(j == 222);
899 CHECK_NOTHROW(ss >> j);
900 CHECK(j == 333);
901
902 CHECK_THROWS_AS(ss >> j, json::parse_error&);
903 CHECK_THROWS_WITH(ss >> j,
904 "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal");
905 }
906
907 SECTION("literals without whitespace")
908 {
909 std::stringstream ss;
910 ss << "truefalsenull\"\"";
911 json j;
912 CHECK_NOTHROW(ss >> j);
913 CHECK(j == true);
914 CHECK_NOTHROW(ss >> j);
915 CHECK(j == false);
916 CHECK_NOTHROW(ss >> j);
917 CHECK(j == nullptr);
918 CHECK_NOTHROW(ss >> j);
919 CHECK(j == "");
920
921 CHECK_THROWS_AS(ss >> j, json::parse_error&);
922 CHECK_THROWS_WITH(ss >> j,
923 "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal");
924 }
925
926 SECTION("example from #529")
927 {
928 std::stringstream ss;
929 ss << "{\n \"one\" : 1,\n \"two\" : 2\n}\n{\n \"three\" : 3\n}";
930 json j;
931 CHECK_NOTHROW(ss >> j);
932 CHECK(j == json({{"one", 1}, {"two", 2}}));
933 CHECK_NOTHROW(ss >> j);
934 CHECK(j == json({{"three", 3}}));
935
936 CHECK_THROWS_AS(ss >> j, json::parse_error&);
937 CHECK_THROWS_WITH(ss >> j,
938 "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal");
939 }
940
941 SECTION("second example from #529")
942 {
943 std::string str = "{\n\"one\" : 1,\n\"two\" : 2\n}\n{\n\"three\" : 3\n}";
944
945 {
946 std::ofstream file("test.json");
947 file << str;
948 }
949
950 std::ifstream stream("test.json", std::ifstream::in);
951 json val;
952
953 size_t i = 0;
954 while (stream.peek() != EOF)
955 {
956 CAPTURE(i)
957 CHECK_NOTHROW(stream >> val);
958
959 CHECK(i < 2);
960
961 if (i == 0)
962 {
963 CHECK(val == json({{"one", 1}, {"two", 2}}));
964 }
965
966 if (i == 1)
967 {
968 CHECK(val == json({{"three", 3}}));
969 }
970
971 ++i;
972 }
973
974 std::remove("test.json");
975 }
976 }
977
978 SECTION("issue #389 - Integer-overflow (OSS-Fuzz issue 267)")
979 {
980 // original test case
981 json j1 = json::parse("-9223372036854775808");
982 CHECK(j1.is_number_integer());
983 CHECK(j1.get<json::number_integer_t>() == INT64_MIN);
984
985 // edge case (+1; still an integer)
986 json j2 = json::parse("-9223372036854775807");
987 CHECK(j2.is_number_integer());
988 CHECK(j2.get<json::number_integer_t>() == INT64_MIN + 1);
989
990 // edge case (-1; overflow -> floats)
991 json j3 = json::parse("-9223372036854775809");
992 CHECK(j3.is_number_float());
993 }
994
995 SECTION("issue #380 - bug in overflow detection when parsing integers")
996 {
997 json j = json::parse("166020696663385964490");
998 CHECK(j.is_number_float());
999 CHECK(j.get<json::number_float_t>() == 166020696663385964490.0);
1000 }
1001
1002 SECTION("issue #405 - Heap-buffer-overflow (OSS-Fuzz issue 342)")
1003 {
1004 // original test case
1005 std::vector<uint8_t> vec {0x65, 0xf5, 0x0a, 0x48, 0x21};
1006 json _;
1007 CHECK_THROWS_AS(_ = json::from_cbor(vec), json::parse_error&);
1008 CHECK_THROWS_WITH(_ = json::from_cbor(vec),
1009 "[json.exception.parse_error.110] parse error at byte 6: syntax error while parsing CBOR string: unexpected end of input");
1010 }
1011
1012 SECTION("issue #407 - Heap-buffer-overflow (OSS-Fuzz issue 343)")
1013 {
1014 json _;
1015
1016 // original test case: incomplete float64
1017 std::vector<uint8_t> vec1 {0xcb, 0x8f, 0x0a};
1018 CHECK_THROWS_AS(_ = json::from_msgpack(vec1), json::parse_error&);
1019 CHECK_THROWS_WITH(_ = json::from_msgpack(vec1),
1020 "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing MessagePack number: unexpected end of input");
1021
1022 // related test case: incomplete float32
1023 std::vector<uint8_t> vec2 {0xca, 0x8f, 0x0a};
1024 CHECK_THROWS_AS(_ = json::from_msgpack(vec2), json::parse_error&);
1025 CHECK_THROWS_WITH(_ = json::from_msgpack(vec2),
1026 "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing MessagePack number: unexpected end of input");
1027
1028 // related test case: incomplete Half-Precision Float (CBOR)
1029 std::vector<uint8_t> vec3 {0xf9, 0x8f};
1030 CHECK_THROWS_AS(_ = json::from_cbor(vec3), json::parse_error&);
1031 CHECK_THROWS_WITH(_ = json::from_cbor(vec3),
1032 "[json.exception.parse_error.110] parse error at byte 3: syntax error while parsing CBOR number: unexpected end of input");
1033
1034 // related test case: incomplete Single-Precision Float (CBOR)
1035 std::vector<uint8_t> vec4 {0xfa, 0x8f, 0x0a};
1036 CHECK_THROWS_AS(_ = json::from_cbor(vec4), json::parse_error&);
1037 CHECK_THROWS_WITH(_ = json::from_cbor(vec4),
1038 "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing CBOR number: unexpected end of input");
1039
1040 // related test case: incomplete Double-Precision Float (CBOR)
1041 std::vector<uint8_t> vec5 {0xfb, 0x8f, 0x0a};
1042 CHECK_THROWS_AS(_ = json::from_cbor(vec5), json::parse_error&);
1043 CHECK_THROWS_WITH(_ = json::from_cbor(vec5),
1044 "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing CBOR number: unexpected end of input");
1045 }
1046
1047 SECTION("issue #408 - Heap-buffer-overflow (OSS-Fuzz issue 344)")
1048 {
1049 json _;
1050
1051 // original test case
1052 std::vector<uint8_t> vec1 {0x87};
1053 CHECK_THROWS_AS(_ = json::from_msgpack(vec1), json::parse_error&);
1054 CHECK_THROWS_WITH(_ = json::from_msgpack(vec1),
1055 "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing MessagePack string: unexpected end of input");
1056
1057 // more test cases for MessagePack
1058 for (auto b :
1059 {
1060 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, // fixmap
1061 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, // fixarray
1062 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, // fixstr
1063 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf
1064 })
1065 {
1066 std::vector<uint8_t> vec(1, static_cast<uint8_t>(b));
1067 CHECK_THROWS_AS(_ = json::from_msgpack(vec), json::parse_error&);
1068 }
1069
1070 // more test cases for CBOR
1071 for (auto b :
1072 {
1073 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
1074 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, // UTF-8 string
1075 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
1076 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, // array
1077 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
1078 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7 // map
1079 })
1080 {
1081 std::vector<uint8_t> vec(1, static_cast<uint8_t>(b));
1082 CHECK_THROWS_AS(_ = json::from_cbor(vec), json::parse_error&);
1083 }
1084
1085 // special case: empty input
1086 std::vector<uint8_t> vec2;
1087 CHECK_THROWS_AS(_ = json::from_cbor(vec2), json::parse_error&);
1088 CHECK_THROWS_WITH(_ = json::from_cbor(vec2),
1089 "[json.exception.parse_error.110] parse error at byte 1: syntax error while parsing CBOR value: unexpected end of input");
1090 CHECK_THROWS_AS(_ = json::from_msgpack(vec2), json::parse_error&);
1091 CHECK_THROWS_WITH(_ = json::from_msgpack(vec2),
1092 "[json.exception.parse_error.110] parse error at byte 1: syntax error while parsing MessagePack value: unexpected end of input");
1093 }
1094
1095 SECTION("issue #411 - Heap-buffer-overflow (OSS-Fuzz issue 366)")
1096 {
1097 json _;
1098
1099 // original test case: empty UTF-8 string (indefinite length)
1100 std::vector<uint8_t> vec1 {0x7f};
1101 CHECK_THROWS_AS(_ = json::from_cbor(vec1), json::parse_error&);
1102 CHECK_THROWS_WITH(_ = json::from_cbor(vec1),
1103 "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing CBOR string: unexpected end of input");
1104
1105 // related test case: empty array (indefinite length)
1106 std::vector<uint8_t> vec2 {0x9f};
1107 CHECK_THROWS_AS(_ = json::from_cbor(vec2), json::parse_error&);
1108 CHECK_THROWS_WITH(_ = json::from_cbor(vec2),
1109 "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing CBOR value: unexpected end of input");
1110
1111 // related test case: empty map (indefinite length)
1112 std::vector<uint8_t> vec3 {0xbf};
1113 CHECK_THROWS_AS(_ = json::from_cbor(vec3), json::parse_error&);
1114 CHECK_THROWS_WITH(_ = json::from_cbor(vec3),
1115 "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing CBOR string: unexpected end of input");
1116 }
1117
1118 SECTION("issue #412 - Heap-buffer-overflow (OSS-Fuzz issue 367)")
1119 {
1120 // original test case
1121 std::vector<uint8_t> vec
1122 {
1123 0xab, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98,
1124 0x98, 0x98, 0x98, 0x98, 0x98, 0x00, 0x00, 0x00,
1125 0x60, 0xab, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98,
1126 0x98, 0x98, 0x98, 0x98, 0x98, 0x00, 0x00, 0x00,
1127 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60,
1128 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60,
1129 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60,
1130 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60,
1131 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60,
1132 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60,
1133 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xa0, 0x9f,
1134 0x9f, 0x97, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60,
1135 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60,
1136 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60,
1137 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60,
1138 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60,
1139 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60
1140 };
1141
1142 json _;
1143 CHECK_THROWS_AS(_ = json::from_cbor(vec), json::parse_error&);
1144 CHECK_THROWS_WITH(_ = json::from_cbor(vec),
1145 "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing CBOR string: expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x98");
1146
1147 // related test case: nonempty UTF-8 string (indefinite length)
1148 std::vector<uint8_t> vec1 {0x7f, 0x61, 0x61};
1149 CHECK_THROWS_AS(_ = json::from_cbor(vec1), json::parse_error&);
1150 CHECK_THROWS_WITH(_ = json::from_cbor(vec1),
1151 "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing CBOR string: unexpected end of input");
1152
1153 // related test case: nonempty array (indefinite length)
1154 std::vector<uint8_t> vec2 {0x9f, 0x01};
1155 CHECK_THROWS_AS(_ = json::from_cbor(vec2), json::parse_error&);
1156 CHECK_THROWS_WITH(_ = json::from_cbor(vec2),
1157 "[json.exception.parse_error.110] parse error at byte 3: syntax error while parsing CBOR value: unexpected end of input");
1158
1159 // related test case: nonempty map (indefinite length)
1160 std::vector<uint8_t> vec3 {0xbf, 0x61, 0x61, 0x01};
1161 CHECK_THROWS_AS(_ = json::from_cbor(vec3), json::parse_error&);
1162 CHECK_THROWS_WITH(_ = json::from_cbor(vec3),
1163 "[json.exception.parse_error.110] parse error at byte 5: syntax error while parsing CBOR string: unexpected end of input");
1164 }
1165
1166 SECTION("issue #414 - compare with literal 0)")
1167 {
1168 #define CHECK_TYPE(v) \
1169 CHECK((json(v) == v));\
1170 CHECK((v == json(v)));\
1171 CHECK_FALSE((json(v) != v));\
1172 CHECK_FALSE((v != json(v)));
1173
1174 CHECK_TYPE(nullptr)
1175 CHECK_TYPE(0)
1176 CHECK_TYPE(0u)
1177 CHECK_TYPE(0L)
1178 CHECK_TYPE(0.0)
1179 CHECK_TYPE("")
1180
1181 #undef CHECK_TYPE
1182 }
1183
1184 SECTION("issue #416 - Use-of-uninitialized-value (OSS-Fuzz issue 377)")
1185 {
1186 // original test case
1187 std::vector<uint8_t> vec1
1188 {
1189 0x94, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
1190 0x3a, 0x96, 0x96, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
1191 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0x71,
1192 0xb4, 0xb4, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0x3a,
1193 0x96, 0x96, 0xb4, 0xb4, 0xfa, 0x94, 0x94, 0x61,
1194 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0xfa
1195 };
1196
1197 json _;
1198 CHECK_THROWS_AS(_ = json::from_cbor(vec1), json::parse_error&);
1199 CHECK_THROWS_WITH(_ = json::from_cbor(vec1),
1200 "[json.exception.parse_error.113] parse error at byte 13: syntax error while parsing CBOR string: expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0xB4");
1201
1202 // related test case: double-precision
1203 std::vector<uint8_t> vec2
1204 {
1205 0x94, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
1206 0x3a, 0x96, 0x96, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
1207 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0x71,
1208 0xb4, 0xb4, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0x3a,
1209 0x96, 0x96, 0xb4, 0xb4, 0xfa, 0x94, 0x94, 0x61,
1210 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0xfb
1211 };
1212 CHECK_THROWS_AS(_ = json::from_cbor(vec2), json::parse_error&);
1213 CHECK_THROWS_WITH(_ = json::from_cbor(vec2),
1214 "[json.exception.parse_error.113] parse error at byte 13: syntax error while parsing CBOR string: expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0xB4");
1215 }
1216
1217 SECTION("issue #452 - Heap-buffer-overflow (OSS-Fuzz issue 585)")
1218 {
1219 std::vector<uint8_t> vec = {'-', '0', '1', '2', '2', '7', '4'};
1220 json _;
1221 CHECK_THROWS_AS(_ = json::parse(vec), json::parse_error&);
1222 }
1223
1224 SECTION("issue #454 - doubles are printed as integers")
1225 {
1226 json j = R"({"bool_value":true,"double_value":2.0,"int_value":10,"level1":{"list_value":[3,"hi",false],"tmp":5.0},"string_value":"hello"})"_json;
1227 CHECK(j["double_value"].is_number_float());
1228 }
1229
1230 SECTION("issue #464 - VS2017 implicit to std::string conversion fix")
1231 {
1232 json v = "test";
1233 std::string test;
1234 test = v;
1235 CHECK(v == "test");
1236 }
1237
1238 SECTION("issue #465 - roundtrip error while parsing 1000000000000000010E5")
1239 {
1240 json j1 = json::parse("1000000000000000010E5");
1241 std::string s1 = j1.dump();
1242 json j2 = json::parse(s1);
1243 std::string s2 = j2.dump();
1244 CHECK(s1 == s2);
1245 }
1246
1247 SECTION("issue #473 - inconsistent behavior in conversion to array type")
1248 {
1249 json j_array = {1, 2, 3, 4};
1250 json j_number = 42;
1251 json j_null = nullptr;
1252
1253 SECTION("std::vector")
1254 {
1255 auto create = [](const json & j)
__anon9ae719c70702(const json & j) 1256 {
1257 std::vector<int> v = j;
1258 };
1259
1260 CHECK_NOTHROW(create(j_array));
1261 CHECK_THROWS_AS(create(j_number), json::type_error&);
1262 CHECK_THROWS_WITH(create(j_number), "[json.exception.type_error.302] type must be array, but is number");
1263 CHECK_THROWS_AS(create(j_null), json::type_error&);
1264 CHECK_THROWS_WITH(create(j_null), "[json.exception.type_error.302] type must be array, but is null");
1265 }
1266
1267 SECTION("std::list")
1268 {
1269 auto create = [](const json & j)
__anon9ae719c70802(const json & j) 1270 {
1271 std::list<int> v = j;
1272 };
1273
1274 CHECK_NOTHROW(create(j_array));
1275 CHECK_THROWS_AS(create(j_number), json::type_error&);
1276 CHECK_THROWS_WITH(create(j_number), "[json.exception.type_error.302] type must be array, but is number");
1277 CHECK_THROWS_AS(create(j_null), json::type_error&);
1278 CHECK_THROWS_WITH(create(j_null), "[json.exception.type_error.302] type must be array, but is null");
1279 }
1280
1281 SECTION("std::forward_list")
1282 {
1283 auto create = [](const json & j)
__anon9ae719c70902(const json & j) 1284 {
1285 std::forward_list<int> v = j;
1286 };
1287
1288 CHECK_NOTHROW(create(j_array));
1289 CHECK_THROWS_AS(create(j_number), json::type_error&);
1290 CHECK_THROWS_WITH(create(j_number), "[json.exception.type_error.302] type must be array, but is number");
1291 CHECK_THROWS_AS(create(j_null), json::type_error&);
1292 CHECK_THROWS_WITH(create(j_null), "[json.exception.type_error.302] type must be array, but is null");
1293 }
1294 }
1295
1296 SECTION("issue #486 - json::value_t can't be a map's key type in VC++ 2015")
1297 {
1298 // the code below must compile with MSVC
1299 std::map<json::value_t, std::string> jsonTypes ;
1300 jsonTypes[json::value_t::array] = "array";
1301 }
1302
1303 SECTION("issue #494 - conversion from vector<bool> to json fails to build")
1304 {
1305 std::vector<bool> boolVector = {false, true, false, false};
1306 json j;
1307 j["bool_vector"] = boolVector;
1308
1309 CHECK(j["bool_vector"].dump() == "[false,true,false,false]");
1310 }
1311
1312 SECTION("issue #504 - assertion error (OSS-Fuzz 856)")
1313 {
1314 std::vector<uint8_t> vec1 = {0xf9, 0xff, 0xff, 0x4a, 0x3a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x37, 0x02, 0x38};
1315 json j1 = json::from_cbor(vec1, false);
1316
1317 // step 2: round trip
1318 std::vector<uint8_t> vec2 = json::to_cbor(j1);
1319
1320 // parse serialization
1321 json j2 = json::from_cbor(vec2);
1322
1323 // NaN is dumped to "null"
1324 CHECK(j2.is_number_float());
1325 CHECK(std::isnan(j2.get<json::number_float_t>()));
1326 CHECK(j2.dump() == "null");
1327
1328 // check if serializations match
1329 CHECK(json::to_cbor(j2) == vec2);
1330 }
1331
1332 SECTION("issue #512 - use of overloaded operator '<=' is ambiguous")
1333 {
1334 json j;
1335 j["a"] = 5;
1336
1337 // json op scalar
1338 CHECK(j["a"] == 5);
1339 CHECK(j["a"] != 4);
1340
1341 CHECK(j["a"] <= 7);
1342 CHECK(j["a"] < 7);
1343 CHECK(j["a"] >= 3);
1344 CHECK(j["a"] > 3);
1345
1346
1347 CHECK(not(j["a"] <= 4));
1348 CHECK(not(j["a"] < 4));
1349 CHECK(not(j["a"] >= 6));
1350 CHECK(not(j["a"] > 6));
1351
1352 // scalar op json
1353 CHECK(5 == j["a"]);
1354 CHECK(4 != j["a"]);
1355
1356 CHECK(7 >= j["a"]);
1357 CHECK(7 > j["a"]);
1358 CHECK(3 <= j["a"]);
1359 CHECK(3 < j["a"]);
1360
1361 CHECK(not(4 >= j["a"]));
1362 CHECK(not(4 > j["a"]));
1363 CHECK(not(6 <= j["a"]));
1364 CHECK(not(6 < j["a"]));
1365 }
1366
1367 SECTION("issue #575 - heap-buffer-overflow (OSS-Fuzz 1400)")
1368 {
1369 json _;
1370 std::vector<uint8_t> vec = {'"', '\\', '"', 'X', '"', '"'};
1371 CHECK_THROWS_AS(_ = json::parse(vec), json::parse_error&);
1372 }
1373
1374 SECTION("issue #600 - how does one convert a map in Json back to std::map?")
1375 {
1376 SECTION("example 1")
1377 {
1378 // create a map
1379 std::map<std::string, int> m1 {{"key", 1}};
1380
1381 // create and print a JSON from the map
1382 json j = m1;
1383
1384 // get the map out of JSON
1385 std::map<std::string, int> m2 = j;
1386
1387 // make sure the roundtrip succeeds
1388 CHECK(m1 == m2);
1389 }
1390
1391 SECTION("example 2")
1392 {
1393 // create a map
1394 std::map<std::string, std::string> m1 {{"key", "val"}};
1395
1396 // create and print a JSON from the map
1397 json j = m1;
1398
1399 // get the map out of JSON
1400 std::map<std::string, std::string> m2 = j;
1401
1402 // make sure the roundtrip succeeds
1403 CHECK(m1 == m2);
1404 }
1405 }
1406
1407 SECTION("issue #602 - BOM not skipped when using json:parse(iterator)")
1408 {
1409 std::string i = "\xef\xbb\xbf{\n \"foo\": true\n}";
1410 json _;
1411 CHECK_NOTHROW(_ = json::parse(i.begin(), i.end()));
1412 }
1413
1414 SECTION("issue #702 - conversion from valarray<double> to json fails to build")
1415 {
1416 SECTION("original example")
1417 {
1418 std::valarray<double> v;
1419 nlohmann::json j;
1420 j["test"] = v;
1421 }
1422
1423 SECTION("full example")
1424 {
1425 std::valarray<double> v = {1.2, 2.3, 3.4, 4.5};
1426 json j = v;
1427 std::valarray<double> vj = j;
1428
1429 CHECK(j == json(vj));
1430 CHECK(v.size() == vj.size());
1431 for (size_t i = 0; i < v.size(); ++i)
1432 {
1433 CHECK(v[i] == vj[i]);
1434 CHECK(v[i] == j[i]);
1435 }
1436
1437 CHECK_THROWS_AS(json().get<std::valarray<double>>(), json::type_error&);
1438 CHECK_THROWS_WITH(json().get<std::valarray<double>>(),
1439 "[json.exception.type_error.302] type must be array, but is null");
1440 }
1441 }
1442
1443 SECTION("issue #367 - Behavior of operator>> should more closely resemble that of built-in overloads.")
1444 {
1445 SECTION("example 1")
1446 {
1447 std::istringstream i1_2_3( "{\"first\": \"one\" }{\"second\": \"two\"}3" );
1448 json j1, j2, j3;
1449 i1_2_3 >> j1;
1450 i1_2_3 >> j2;
1451 i1_2_3 >> j3;
1452
1453 std::map<std::string, std::string> m1 = j1;
1454 std::map<std::string, std::string> m2 = j2;
1455 int i3 = j3;
1456
1457 CHECK( m1 == ( std::map<std::string, std::string> {{ "first", "one" }} ));
1458 CHECK( m2 == ( std::map<std::string, std::string> {{ "second", "two" }} ));
1459 CHECK( i3 == 3 );
1460 }
1461 }
1462
1463 SECTION("issue #714 - throw std::ios_base::failure exception when failbit set to true")
1464 {
1465 {
1466 std::ifstream is;
1467 is.exceptions(
1468 is.exceptions()
1469 | std::ios_base::failbit
1470 | std::ios_base::badbit
1471 ); // handle different exceptions as 'file not found', 'permission denied'
1472
1473 is.open("test/data/regression/working_file.json");
1474 json _;
1475 CHECK_NOTHROW(_ = nlohmann::json::parse(is));
1476 }
1477
1478 {
1479 std::ifstream is;
1480 is.exceptions(
1481 is.exceptions()
1482 | std::ios_base::failbit
1483 | std::ios_base::badbit
1484 ); // handle different exceptions as 'file not found', 'permission denied'
1485
1486 is.open("test/data/json_nlohmann_tests/all_unicode.json.cbor",
1487 std::ios_base::in | std::ios_base::binary);
1488 json _;
1489 CHECK_NOTHROW(_ = nlohmann::json::from_cbor(is));
1490 }
1491 }
1492
1493 SECTION("issue #805 - copy constructor is used with std::initializer_list constructor.")
1494 {
1495 nocopy n;
1496 json j;
1497 j = {{"nocopy", n}};
1498 CHECK(j["nocopy"]["val"] == 0);
1499 }
1500
1501 SECTION("issue #838 - incorrect parse error with binary data in keys")
1502 {
1503 uint8_t key1[] = { 103, 92, 117, 48, 48, 48, 55, 92, 114, 215, 126, 214, 95, 92, 34, 174, 40, 71, 38, 174, 40, 71, 38, 223, 134, 247, 127 };
1504 std::string key1_str(key1, key1 + sizeof(key1) / sizeof(key1[0]));
1505 json j = key1_str;
1506 CHECK_THROWS_AS(j.dump(), json::type_error&);
1507 CHECK_THROWS_WITH(j.dump(), "[json.exception.type_error.316] invalid UTF-8 byte at index 10: 0x7E");
1508 }
1509
1510 SECTION("issue #843 - converting to array not working")
1511 {
1512 json j;
1513 std::array<int, 4> ar = {{1, 1, 1, 1}};
1514 j = ar;
1515 ar = j;
1516 }
1517
1518 SECTION("issue #894 - invalid RFC6902 copy operation succeeds")
1519 {
1520 auto model = R"({
1521 "one": {
1522 "two": {
1523 "three": "hello",
1524 "four": 42
1525 }
1526 }
1527 })"_json;
1528
1529 auto p1 = R"([{"op": "move",
1530 "from": "/one/two/three",
1531 "path": "/a/b/c"}])"_json;
1532 CHECK_THROWS_AS(model.patch(p1), json::out_of_range&);
1533
1534 auto p2 = R"([{"op": "move",
1535 "from": "/one/two/three",
1536 "path": "/a/b/c"}])"_json;
1537 CHECK_THROWS_WITH(model.patch(p2),
1538 "[json.exception.out_of_range.403] key 'a' not found");
1539
1540 auto p3 = R"([{"op": "copy",
1541 "from": "/one/two/three",
1542 "path": "/a/b/c"}])"_json;
1543 CHECK_THROWS_AS(model.patch(p3), json::out_of_range&);
1544
1545 auto p4 = R"([{"op": "copy",
1546 "from": "/one/two/three",
1547 "path": "/a/b/c"}])"_json;
1548 CHECK_THROWS_WITH(model.patch(p4),
1549 "[json.exception.out_of_range.403] key 'a' not found");
1550 }
1551
1552 SECTION("issue #961 - incorrect parsing of indefinite length CBOR strings")
1553 {
1554 std::vector<uint8_t> v_cbor =
1555 {
1556 0x7F,
1557 0x64,
1558 'a', 'b', 'c', 'd',
1559 0x63,
1560 '1', '2', '3',
1561 0xFF
1562 };
1563 json j = json::from_cbor(v_cbor);
1564 CHECK(j == "abcd123");
1565 }
1566
1567 SECTION("issue #962 - Timeout (OSS-Fuzz 6034)")
1568 {
1569 json _;
1570 std::vector<uint8_t> v_ubjson = {'[', '$', 'Z', '#', 'L', 0x78, 0x28, 0x00, 0x68, 0x28, 0x69, 0x69, 0x17};
1571 CHECK_THROWS_AS(_ = json::from_ubjson(v_ubjson), json::out_of_range&);
1572 //CHECK_THROWS_WITH(json::from_ubjson(v_ubjson),
1573 // "[json.exception.out_of_range.408] excessive array size: 8658170730974374167");
1574
1575 v_ubjson[0] = '{';
1576 CHECK_THROWS_AS(_ = json::from_ubjson(v_ubjson), json::out_of_range&);
1577 //CHECK_THROWS_WITH(json::from_ubjson(v_ubjson),
1578 // "[json.exception.out_of_range.408] excessive object size: 8658170730974374167");
1579 }
1580
1581 SECTION("issue #971 - Add a SAX parser - late bug")
1582 {
1583 // a JSON text
1584 auto text = R"(
1585 {
1586 "Image": {
1587 "Width": 800,
1588 "Height": 600,
1589 "Title": "View from 15th Floor",
1590 "Thumbnail": {
1591 "Url": "http://www.example.com/image/481989943",
1592 "Height": 125,
1593 "Width": 100
1594 },
1595 "Animated" : false,
1596 "IDs": [116, 943, 234, 38793]
1597 }
1598 }
1599 )";
1600
1601 // define parser callback
1602 json::parser_callback_t cb = [](int /*depth*/, json::parse_event_t event, json & parsed)
__anon9ae719c70a02(int , json::parse_event_t event, json & parsed) 1603 {
1604 // skip object elements with key "Thumbnail"
1605 if (event == json::parse_event_t::key and parsed == json("Thumbnail"))
1606 {
1607 return false;
1608 }
1609 else
1610 {
1611 return true;
1612 }
1613 };
1614
1615 // parse (with callback) and serialize JSON
1616 json j_filtered = json::parse(text, cb);
1617
1618 CHECK(j_filtered == R"({"Image":{"Animated":false,"Height":600,"IDs":[116,943,234,38793], "Title":"View from 15th Floor","Width":800}})"_json);
1619 }
1620
1621 SECTION("issue #972 - Segmentation fault on G++ when trying to assign json string literal to custom json type")
1622 {
1623 my_json foo = R"([1, 2, 3])"_json;
1624 }
1625
1626 SECTION("issue #977 - Assigning between different json types")
1627 {
1628 foo_json lj = ns::foo{3};
1629 ns::foo ff = lj;
1630 CHECK(lj.is_object());
1631 CHECK(lj.size() == 1);
1632 CHECK(lj["x"] == 3);
1633 CHECK(ff.x == 3);
1634 nlohmann::json nj = lj; // This line works as expected
1635 }
1636
1637 SECTION("issue #1001 - Fix memory leak during parser callback")
1638 {
1639 auto geojsonExample = R"(
1640 { "type": "FeatureCollection",
1641 "features": [
1642 { "type": "Feature",
1643 "geometry": {"type": "Point", "coordinates": [102.0, 0.5]},
1644 "properties": {"prop0": "value0"}
1645 },
1646 { "type": "Feature",
1647 "geometry": {
1648 "type": "LineString",
1649 "coordinates": [
1650 [102.0, 0.0], [103.0, 1.0], [104.0, 0.0], [105.0, 1.0]
1651 ]
1652 },
1653 "properties": {
1654 "prop0": "value0",
1655 "prop1": 0.0
1656 }
1657 },
1658 { "type": "Feature",
1659 "geometry": {
1660 "type": "Polygon",
1661 "coordinates": [
1662 [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0],
1663 [100.0, 1.0], [100.0, 0.0] ]
1664 ]
1665 },
1666 "properties": {
1667 "prop0": "value0",
1668 "prop1": {"this": "that"}
1669 }
1670 }
1671 ]
1672 })";
1673
1674 json::parser_callback_t cb = [&](int, json::parse_event_t event, json & parsed)
__anon9ae719c70b02(int, json::parse_event_t event, json & parsed) 1675 {
1676 // skip uninteresting events
1677 if (event == json::parse_event_t::value and !parsed.is_primitive())
1678 {
1679 return false;
1680 }
1681
1682 switch (event)
1683 {
1684 case json::parse_event_t::key:
1685 {
1686 return true;
1687 }
1688 case json::parse_event_t::value:
1689 {
1690 return false;
1691 }
1692 case json::parse_event_t::object_start:
1693 {
1694 return true;
1695 }
1696 case json::parse_event_t::object_end:
1697 {
1698 return false;
1699 }
1700 case json::parse_event_t::array_start:
1701 {
1702 return true;
1703 }
1704 case json::parse_event_t::array_end:
1705 {
1706 return false;
1707 }
1708
1709 default:
1710 {
1711 return true;
1712 }
1713 }
1714 };
1715
1716 auto j = json::parse(geojsonExample, cb, true);
1717 CHECK(j == json());
1718 }
1719
1720 SECTION("issue #1021 - to/from_msgpack only works with standard typization")
1721 {
1722 float_json j = 1000.0;
1723 CHECK(float_json::from_cbor(float_json::to_cbor(j)) == j);
1724 CHECK(float_json::from_msgpack(float_json::to_msgpack(j)) == j);
1725 CHECK(float_json::from_ubjson(float_json::to_ubjson(j)) == j);
1726
1727 float_json j2 = {1000.0, 2000.0, 3000.0};
1728 CHECK(float_json::from_ubjson(float_json::to_ubjson(j2, true, true)) == j2);
1729 }
1730
1731 SECTION("issue #1045 - Using STL algorithms with JSON containers with expected results?")
1732 {
1733 json diffs = nlohmann::json::array();
1734 json m1{{"key1", 42}};
1735 json m2{{"key2", 42}};
1736 auto p1 = m1.items();
1737 auto p2 = m2.items();
1738
1739 using it_type = decltype(p1.begin());
1740
1741 std::set_difference(
1742 p1.begin(), p1.end(),
1743 p2.begin(), p2.end(),
1744 std::inserter(diffs, diffs.end()), [&](const it_type & e1, const it_type & e2) -> bool
1745 {
1746 using comper_pair = std::pair<std::string, decltype(e1.value())>; // Trying to avoid unneeded copy
1747 return comper_pair(e1.key(), e1.value()) < comper_pair(e2.key(), e2.value()); // Using pair comper
1748 });
1749
1750 CHECK(diffs.size() == 1); // Note the change here, was 2
1751 }
1752
1753 #ifdef JSON_HAS_CPP_17
1754 SECTION("issue #1292 - Serializing std::variant causes stack overflow")
1755 {
1756 static_assert(
1757 not std::is_constructible<json, std::variant<int, float>>::value, "");
1758 }
1759 #endif
1760
1761 SECTION("issue #1299 - compile error in from_json converting to container "
1762 "with std::pair")
1763 {
1764 json j =
1765 {
1766 {"1", {{"a", "testa_1"}, {"b", "testb_1"}}},
1767 {"2", {{"a", "testa_2"}, {"b", "testb_2"}}},
1768 {"3", {{"a", "testa_3"}, {"b", "testb_3"}}},
1769 };
1770
1771 std::map<std::string, Data> expected
1772 {
1773 {"1", {"testa_1", "testb_1"}},
1774 {"2", {"testa_2", "testb_2"}},
1775 {"3", {"testa_3", "testb_3"}},
1776 };
1777 const auto data = j.get<decltype(expected)>();
1778 CHECK(expected == data);
1779 }
1780
1781 SECTION("issue #1445 - buffer overflow in dumping invalid utf-8 strings")
1782 {
1783 SECTION("a bunch of -1, ensure_ascii=true")
1784 {
1785 const auto length = 300;
1786
1787 json dump_test;
1788 dump_test["1"] = std::string(length, -1);
1789
1790 std::string expected = "{\"1\":\"";
1791 for (int i = 0; i < length; ++i)
1792 {
1793 expected += "\\ufffd";
1794 }
1795 expected += "\"}";
1796
1797 auto s = dump_test.dump(-1, ' ', true, nlohmann::json::error_handler_t::replace);
1798 CHECK(s == expected);
1799 }
1800 SECTION("a bunch of -2, ensure_ascii=false")
1801 {
1802 const auto length = 500;
1803
1804 json dump_test;
1805 dump_test["1"] = std::string(length, -2);
1806
1807 std::string expected = "{\"1\":\"";
1808 for (int i = 0; i < length; ++i)
1809 {
1810 expected += "\xEF\xBF\xBD";
1811 }
1812 expected += "\"}";
1813
1814 auto s = dump_test.dump(-1, ' ', false, nlohmann::json::error_handler_t::replace);
1815 CHECK(s == expected);
1816 }
1817 SECTION("test case in issue #1445")
1818 {
1819 nlohmann::json dump_test;
1820 const int data[] =
1821 {
1822 109, 108, 103, 125, -122, -53, 115,
1823 18, 3, 0, 102, 19, 1, 15,
1824 -110, 13, -3, -1, -81, 32, 2,
1825 0, 0, 0, 0, 0, 0, 0,
1826 8, 0, 0, 0, 0, 0, 0,
1827 0, 0, 0, 0, 0, -80, 2,
1828 0, 0, 96, -118, 46, -116, 46,
1829 109, -84, -87, 108, 14, 109, -24,
1830 -83, 13, -18, -51, -83, -52, -115,
1831 14, 6, 32, 0, 0, 0, 0,
1832 0, 0, 0, 0, 0, 0, 0,
1833 64, 3, 0, 0, 0, 35, -74,
1834 -73, 55, 57, -128, 0, 0, 0,
1835 0, 0, 0, 0, 0, 0, 0,
1836 0, 0, 33, 0, 0, 0, -96,
1837 -54, -28, -26
1838 };
1839 std::string s;
1840 for (unsigned i = 0; i < sizeof(data) / sizeof(int); i++)
1841 {
1842 s += static_cast<char>(data[i]);
1843 }
1844 dump_test["1"] = s;
1845 dump_test.dump(-1, ' ', true, nlohmann::json::error_handler_t::replace);
1846 }
1847 }
1848
1849 SECTION("issue #1447 - Integer Overflow (OSS-Fuzz 12506)")
1850 {
1851 json j = json::parse("[-9223372036854775808]");
1852 CHECK(j.dump() == "[-9223372036854775808]");
1853 }
1854
1855 SECTION("issue #1708 - minimum value of int64_t can be outputted")
1856 {
1857 constexpr auto smallest = (std::numeric_limits<int64_t>::min)();
1858 json j = smallest;
1859 CHECK(j.dump() == std::to_string(smallest));
1860 }
1861
1862 SECTION("issue #1727 - Contains with non-const lvalue json_pointer picks the wrong overload")
1863 {
1864 json j = {{"root", {{"settings", {{"logging", true}}}}}};
1865
1866 auto jptr1 = "/root/settings/logging"_json_pointer;
1867 auto jptr2 = json::json_pointer{"/root/settings/logging"};
1868
1869 CHECK(j.contains(jptr1));
1870 CHECK(j.contains(jptr2));
1871 }
1872
1873 SECTION("issue #1647 - compile error when deserializing enum if both non-default from_json and non-member operator== exists for other type")
1874 {
1875 {
1876 json j;
1877 NonDefaultFromJsonStruct x = j;
1878 NonDefaultFromJsonStruct y;
1879 CHECK(x == y);
1880 }
1881
1882 auto val = nlohmann::json("one").get<for_1647>();
1883 CHECK(val == for_1647::one);
1884 json j = val;
1885 }
1886
1887 SECTION("issue #1805 - A pair<T1, T2> is json constructible only if T1 and T2 are json constructible")
1888 {
1889 static_assert(!std::is_constructible<json, std::pair<std::string, NotSerializableData>>::value, "");
1890 static_assert(!std::is_constructible<json, std::pair<NotSerializableData, std::string>>::value, "");
1891 static_assert(std::is_constructible<json, std::pair<int, std::string>>::value, "");
1892 }
1893 SECTION("issue #1825 - A tuple<Args..> is json constructible only if all T in Args are json constructible")
1894 {
1895 static_assert(!std::is_constructible<json, std::tuple<std::string, NotSerializableData>>::value, "");
1896 static_assert(!std::is_constructible<json, std::tuple<NotSerializableData, std::string>>::value, "");
1897 static_assert(std::is_constructible<json, std::tuple<int, std::string>>::value, "");
1898 }
1899 }
1900
1901 #if not defined(JSON_NOEXCEPTION)
1902 TEST_CASE("regression tests, exceptions dependent")
1903 {
1904 SECTION("issue #1340 - eof not set on exhausted input stream")
1905 {
1906 std::stringstream s("{}{}");
1907 json j;
1908 s >> j;
1909 s >> j;
1910 CHECK_THROWS_AS(s >> j, json::parse_error const&);
1911 CHECK(s.eof());
1912 }
1913 }
1914 #endif
1915
1916 /////////////////////////////////////////////////////////////////////
1917 // for #1642
1918 /////////////////////////////////////////////////////////////////////
1919 template <typename T> class array {};
1920 template <typename T> class object {};
1921 template <typename T> class string {};
1922 template <typename T> class number_integer {};
1923 template <typename T> class number_unsigned {};
1924 template <typename T> class number_float {};
1925