3 __| | __| | | | JSON for Modern C++ (test suite)
4 | | |__ | | | | | | version 3.10.5
5 |_____|_____|_____|_|___| https://github.com/nlohmann/json
7 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
8 SPDX-License-Identifier: MIT
9 Copyright (c) 2013-2022 Niels Lohmann <http://nlohmann.me>.
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:
18 The above copyright notice and this permission notice shall be included in all
19 copies or substantial portions of the Software.
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
30 #include "doctest_compatibility.h"
32 #include <nlohmann/json.hpp>
41 struct SaxEventLogger
: public nlohmann::json_sax
<json
>
45 events
.emplace_back("null()");
49 bool boolean(bool val
) override
51 events
.emplace_back(val
? "boolean(true)" : "boolean(false)");
55 bool number_integer(json::number_integer_t val
) override
57 events
.push_back("number_integer(" + std::to_string(val
) + ")");
61 bool number_unsigned(json::number_unsigned_t val
) override
63 events
.push_back("number_unsigned(" + std::to_string(val
) + ")");
67 bool number_float(json::number_float_t
/*val*/, const std::string
& s
) override
69 events
.push_back("number_float(" + s
+ ")");
73 bool string(std::string
& val
) override
75 events
.push_back("string(" + val
+ ")");
79 bool binary(json::binary_t
& val
) override
81 std::string binary_contents
= "binary(";
82 std::string comma_space
;
85 binary_contents
.append(comma_space
);
86 binary_contents
.append(std::to_string(static_cast<int>(b
)));
89 binary_contents
.append(")");
90 events
.push_back(binary_contents
);
94 bool start_object(std::size_t elements
) override
96 if (elements
== static_cast<std::size_t>(-1))
98 events
.emplace_back("start_object()");
102 events
.push_back("start_object(" + std::to_string(elements
) + ")");
107 bool key(std::string
& val
) override
109 events
.push_back("key(" + val
+ ")");
113 bool end_object() override
115 events
.emplace_back("end_object()");
119 bool start_array(std::size_t elements
) override
121 if (elements
== static_cast<std::size_t>(-1))
123 events
.emplace_back("start_array()");
127 events
.push_back("start_array(" + std::to_string(elements
) + ")");
132 bool end_array() override
134 events
.emplace_back("end_array()");
138 bool parse_error(std::size_t position
, const std::string
& /*last_token*/, const json::exception
& /*ex*/) override
140 events
.push_back("parse_error(" + std::to_string(position
) + ")");
144 std::vector
<std::string
> events
{};
147 struct SaxEventLoggerExitAfterStartObject
: public SaxEventLogger
149 bool start_object(std::size_t elements
) override
151 if (elements
== static_cast<std::size_t>(-1))
153 events
.emplace_back("start_object()");
157 events
.push_back("start_object(" + std::to_string(elements
) + ")");
163 struct SaxEventLoggerExitAfterKey
: public SaxEventLogger
165 bool key(std::string
& val
) override
167 events
.push_back("key(" + val
+ ")");
172 struct SaxEventLoggerExitAfterStartArray
: public SaxEventLogger
174 bool start_array(std::size_t elements
) override
176 if (elements
== static_cast<std::size_t>(-1))
178 events
.emplace_back("start_array()");
182 events
.push_back("start_array(" + std::to_string(elements
) + ")");
189 TEST_CASE("deserialization")
191 SECTION("successful deserialization")
195 std::stringstream ss1
;
196 std::stringstream ss2
;
197 std::stringstream ss3
;
198 ss1
<< R
"(["foo
",1,2,3,false,{"one
":1}])";
199 ss2
<< R
"(["foo
",1,2,3,false,{"one
":1}])";
200 ss3
<< R
"(["foo
",1,2,3,false,{"one
":1}])";
201 json j
= json::parse(ss1
);
202 CHECK(json::accept(ss2
));
203 CHECK(j
== json({"foo", 1, 2, 3, false, {{"one", 1}}}));
206 CHECK(json::sax_parse(ss3
, &l
));
207 CHECK(l
.events
.size() == 11);
208 CHECK(l
.events
== std::vector
<std::string
>(
210 "start_array()", "string(foo)", "number_unsigned(1)",
211 "number_unsigned(2)", "number_unsigned(3)", "boolean(false)",
212 "start_object()", "key(one)", "number_unsigned(1)",
213 "end_object()", "end_array()"
217 SECTION("string literal")
219 const auto* s
= R
"(["foo
",1,2,3,false,{"one
":1}])";
220 json j
= json::parse(s
);
221 CHECK(json::accept(s
));
222 CHECK(j
== json({"foo", 1, 2, 3, false, {{"one", 1}}}));
225 CHECK(json::sax_parse(s
, &l
));
226 CHECK(l
.events
.size() == 11);
227 CHECK(l
.events
== std::vector
<std::string
>(
229 "start_array()", "string(foo)", "number_unsigned(1)",
230 "number_unsigned(2)", "number_unsigned(3)", "boolean(false)",
231 "start_object()", "key(one)", "number_unsigned(1)",
232 "end_object()", "end_array()"
238 json::string_t s
= R
"(["foo
",1,2,3,false,{"one
":1}])";
239 json j
= json::parse(s
);
240 CHECK(json::accept(s
));
241 CHECK(j
== json({"foo", 1, 2, 3, false, {{"one", 1}}}));
244 CHECK(json::sax_parse(s
, &l
));
245 CHECK(l
.events
.size() == 11);
246 CHECK(l
.events
== std::vector
<std::string
>(
248 "start_array()", "string(foo)", "number_unsigned(1)",
249 "number_unsigned(2)", "number_unsigned(3)", "boolean(false)",
250 "start_object()", "key(one)", "number_unsigned(1)",
251 "end_object()", "end_array()"
255 SECTION("operator<<")
257 std::stringstream ss
;
258 ss
<< R
"(["foo
",1,2,3,false,{"one
":1}])";
261 CHECK(j
== json({"foo", 1, 2, 3, false, {{"one", 1}}}));
264 SECTION("operator>>")
266 std::stringstream ss
;
267 ss
<< R
"(["foo
",1,2,3,false,{"one
":1}])";
270 CHECK(j
== json({"foo", 1, 2, 3, false, {{"one", 1}}}));
273 SECTION("user-defined string literal")
275 CHECK("[\"foo\",1,2,3,false,{\"one\":1}]"_json
== json({"foo", 1, 2, 3, false, {{"one", 1}}}));
279 SECTION("unsuccessful deserialization")
283 std::stringstream ss1
;
284 std::stringstream ss2
;
285 std::stringstream ss3
;
286 std::stringstream ss4
;
287 std::stringstream ss5
;
288 ss1
<< R
"(["foo
",1,2,3,false,{"one
":1})";
289 ss2
<< R
"(["foo
",1,2,3,false,{"one
":1})";
290 ss3
<< R
"(["foo
",1,2,3,false,{"one
":1})";
291 ss4
<< R
"(["foo
",1,2,3,false,{"one
":1})";
292 ss5
<< R
"(["foo
",1,2,3,false,{"one
":1})";
295 CHECK_THROWS_AS(_
= json::parse(ss1
), json::parse_error
&);
296 CHECK_THROWS_WITH(_
= json::parse(ss2
),
297 "[json.exception.parse_error.101] parse error at line 1, column 29: syntax error while parsing array - unexpected end of input; expected ']'");
298 CHECK(!json::accept(ss3
));
301 CHECK_NOTHROW(j_error
= json::parse(ss4
, nullptr, false));
302 CHECK(j_error
.is_discarded());
305 CHECK(!json::sax_parse(ss5
, &l
));
306 CHECK(l
.events
.size() == 11);
307 CHECK(l
.events
== std::vector
<std::string
>(
309 "start_array()", "string(foo)", "number_unsigned(1)",
310 "number_unsigned(2)", "number_unsigned(3)", "boolean(false)",
311 "start_object()", "key(one)", "number_unsigned(1)",
312 "end_object()", "parse_error(29)"
318 json::string_t s
= R
"(["foo
",1,2,3,false,{"one
":1})";
320 CHECK_THROWS_AS(_
= json::parse(s
), json::parse_error
&);
321 CHECK_THROWS_WITH(_
= json::parse(s
),
322 "[json.exception.parse_error.101] parse error at line 1, column 29: syntax error while parsing array - unexpected end of input; expected ']'");
323 CHECK(!json::accept(s
));
326 CHECK_NOTHROW(j_error
= json::parse(s
, nullptr, false));
327 CHECK(j_error
.is_discarded());
330 CHECK(!json::sax_parse(s
, &l
));
331 CHECK(l
.events
.size() == 11);
332 CHECK(l
.events
== std::vector
<std::string
>(
334 "start_array()", "string(foo)", "number_unsigned(1)",
335 "number_unsigned(2)", "number_unsigned(3)", "boolean(false)",
336 "start_object()", "key(one)", "number_unsigned(1)",
337 "end_object()", "parse_error(29)"
341 SECTION("operator<<")
343 std::stringstream ss1
;
344 std::stringstream ss2
;
345 ss1
<< R
"(["foo
",1,2,3,false,{"one
":1})";
346 ss2
<< R
"(["foo
",1,2,3,false,{"one
":1})";
348 CHECK_THROWS_AS(j
<< ss1
, json::parse_error
&);
349 CHECK_THROWS_WITH(j
<< ss2
,
350 "[json.exception.parse_error.101] parse error at line 1, column 29: syntax error while parsing array - unexpected end of input; expected ']'");
353 SECTION("operator>>")
355 std::stringstream ss1
;
356 std::stringstream ss2
;
357 ss1
<< R
"(["foo
",1,2,3,false,{"one
":1})";
358 ss2
<< R
"(["foo
",1,2,3,false,{"one
":1})";
360 CHECK_THROWS_AS(ss1
>> j
, json::parse_error
&);
361 CHECK_THROWS_WITH(ss2
>> j
,
362 "[json.exception.parse_error.101] parse error at line 1, column 29: syntax error while parsing array - unexpected end of input; expected ']'");
365 SECTION("user-defined string literal")
367 CHECK_THROWS_AS("[\"foo\",1,2,3,false,{\"one\":1}"_json
, json::parse_error
&);
368 CHECK_THROWS_WITH("[\"foo\",1,2,3,false,{\"one\":1}"_json
,
369 "[json.exception.parse_error.101] parse error at line 1, column 29: syntax error while parsing array - unexpected end of input; expected ']'");
373 SECTION("contiguous containers")
377 SECTION("from std::vector")
379 std::vector
<uint8_t> v
= {'t', 'r', 'u', 'e'};
380 CHECK(json::parse(v
) == json(true));
381 CHECK(json::accept(v
));
384 CHECK(json::sax_parse(v
, &l
));
385 CHECK(l
.events
.size() == 1);
386 CHECK(l
.events
== std::vector
<std::string
>({"boolean(true)"}));
389 SECTION("from std::array")
391 std::array
<uint8_t, 5> v
{ {'t', 'r', 'u', 'e'} };
392 CHECK(json::parse(v
) == json(true));
393 CHECK(json::accept(v
));
396 CHECK(json::sax_parse(v
, &l
));
397 CHECK(l
.events
.size() == 1);
398 CHECK(l
.events
== std::vector
<std::string
>({"boolean(true)"}));
401 SECTION("from array")
403 uint8_t v
[] = {'t', 'r', 'u', 'e'}; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
404 CHECK(json::parse(v
) == json(true));
405 CHECK(json::accept(v
));
408 CHECK(json::sax_parse(v
, &l
));
409 CHECK(l
.events
.size() == 1);
410 CHECK(l
.events
== std::vector
<std::string
>({"boolean(true)"}));
413 SECTION("from chars")
415 auto* v
= new uint8_t[5]; // NOLINT(cppcoreguidelines-owning-memory)
421 CHECK(json::parse(v
) == json(true));
422 CHECK(json::accept(v
));
425 CHECK(json::sax_parse(v
, &l
));
426 CHECK(l
.events
.size() == 1);
427 CHECK(l
.events
== std::vector
<std::string
>({"boolean(true)"}));
429 delete[] v
; // NOLINT(cppcoreguidelines-owning-memory)
432 SECTION("from std::string")
434 std::string v
= {'t', 'r', 'u', 'e'};
435 CHECK(json::parse(v
) == json(true));
436 CHECK(json::accept(v
));
439 CHECK(json::sax_parse(v
, &l
));
440 CHECK(l
.events
.size() == 1);
441 CHECK(l
.events
== std::vector
<std::string
>({"boolean(true)"}));
444 SECTION("from std::initializer_list")
446 std::initializer_list
<uint8_t> v
= {'t', 'r', 'u', 'e'};
447 CHECK(json::parse(v
) == json(true));
448 CHECK(json::accept(v
));
451 CHECK(json::sax_parse(v
, &l
));
452 CHECK(l
.events
.size() == 1);
453 CHECK(l
.events
== std::vector
<std::string
>({"boolean(true)"}));
456 SECTION("empty container")
458 std::vector
<uint8_t> v
;
460 CHECK_THROWS_AS(_
= json::parse(v
), json::parse_error
&);
461 CHECK(!json::accept(v
));
464 CHECK(!json::sax_parse(v
, &l
));
465 CHECK(l
.events
.size() == 1);
466 CHECK(l
.events
== std::vector
<std::string
>({"parse_error(1)"}));
470 SECTION("via iterator range")
472 SECTION("from std::vector")
474 std::vector
<uint8_t> v
= {'t', 'r', 'u', 'e'};
475 CHECK(json::parse(std::begin(v
), std::end(v
)) == json(true));
476 CHECK(json::accept(std::begin(v
), std::end(v
)));
479 CHECK(json::sax_parse(std::begin(v
), std::end(v
), &l
));
480 CHECK(l
.events
.size() == 1);
481 CHECK(l
.events
== std::vector
<std::string
>({"boolean(true)"}));
485 SECTION("from std::array")
487 std::array
<uint8_t, 5> v
{ {'t', 'r', 'u', 'e'} };
488 CHECK(json::parse(std::begin(v
), std::end(v
)) == json(true));
489 CHECK(json::accept(std::begin(v
), std::end(v
)));
492 CHECK(json::sax_parse(std::begin(v
), std::end(v
), &l
));
493 CHECK(l
.events
.size() == 1);
494 CHECK(l
.events
== std::vector
<std::string
>({"boolean(true)"}));
497 SECTION("from array")
499 uint8_t v
[] = {'t', 'r', 'u', 'e'}; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
500 CHECK(json::parse(std::begin(v
), std::end(v
)) == json(true));
501 CHECK(json::accept(std::begin(v
), std::end(v
)));
504 CHECK(json::sax_parse(std::begin(v
), std::end(v
), &l
));
505 CHECK(l
.events
.size() == 1);
506 CHECK(l
.events
== std::vector
<std::string
>({"boolean(true)"}));
509 SECTION("from std::string")
511 std::string v
= {'t', 'r', 'u', 'e'};
512 CHECK(json::parse(std::begin(v
), std::end(v
)) == json(true));
513 CHECK(json::accept(std::begin(v
), std::end(v
)));
516 CHECK(json::sax_parse(std::begin(v
), std::end(v
), &l
));
517 CHECK(l
.events
.size() == 1);
518 CHECK(l
.events
== std::vector
<std::string
>({"boolean(true)"}));
521 SECTION("from std::initializer_list")
523 std::initializer_list
<uint8_t> v
= {'t', 'r', 'u', 'e'};
524 CHECK(json::parse(std::begin(v
), std::end(v
)) == json(true));
525 CHECK(json::accept(std::begin(v
), std::end(v
)));
528 CHECK(json::sax_parse(std::begin(v
), std::end(v
), &l
));
529 CHECK(l
.events
.size() == 1);
530 CHECK(l
.events
== std::vector
<std::string
>({"boolean(true)"}));
533 SECTION("from std::valarray")
535 std::valarray
<uint8_t> v
= {'t', 'r', 'u', 'e'};
536 CHECK(json::parse(std::begin(v
), std::end(v
)) == json(true));
537 CHECK(json::accept(std::begin(v
), std::end(v
)));
540 CHECK(json::sax_parse(std::begin(v
), std::end(v
), &l
));
541 CHECK(l
.events
.size() == 1);
542 CHECK(l
.events
== std::vector
<std::string
>({"boolean(true)"}));
545 SECTION("with empty range")
547 std::vector
<uint8_t> v
;
549 CHECK_THROWS_AS(_
= json::parse(std::begin(v
), std::end(v
)), json::parse_error
&);
550 CHECK(!json::accept(std::begin(v
), std::end(v
)));
553 CHECK(!json::sax_parse(std::begin(v
), std::end(v
), &l
));
554 CHECK(l
.events
.size() == 1);
555 CHECK(l
.events
== std::vector
<std::string
>({"parse_error(1)"}));
559 // these cases are required for 100% line coverage
560 SECTION("error cases")
564 std::array
<std::uint8_t, 9> v
= {{'\"', 'a', 'a', 'a', 'a', 'a', 'a', '\\', 'u'}};
566 CHECK_THROWS_AS(_
= json::parse(std::begin(v
), std::end(v
)), json::parse_error
&);
567 CHECK(!json::accept(std::begin(v
), std::end(v
)));
570 CHECK_NOTHROW(j_error
= json::parse(std::begin(v
), std::end(v
), nullptr, false));
571 CHECK(j_error
.is_discarded());
574 CHECK(!json::sax_parse(std::begin(v
), std::end(v
), &l
));
575 CHECK(l
.events
.size() == 1);
576 CHECK(l
.events
== std::vector
<std::string
>({"parse_error(10)"}));
581 std::array
<std::uint8_t, 10> v
= {{'\"', 'a', 'a', 'a', 'a', 'a', 'a', '\\', 'u', '1'}};
583 CHECK_THROWS_AS(_
= json::parse(std::begin(v
), std::end(v
)), json::parse_error
&);
584 CHECK(!json::accept(std::begin(v
), std::end(v
)));
587 CHECK_NOTHROW(j_error
= json::parse(std::begin(v
), std::end(v
), nullptr, false));
588 CHECK(j_error
.is_discarded());
591 CHECK(!json::sax_parse(std::begin(v
), std::end(v
), &l
));
592 CHECK(l
.events
.size() == 1);
593 CHECK(l
.events
== std::vector
<std::string
>({"parse_error(11)"}));
598 std::array
<std::uint8_t, 17> v
= {{'\"', 'a', 'a', 'a', 'a', 'a', 'a', '\\', 'u', '1', '1', '1', '1', '1', '1', '1', '1'}};
600 CHECK_THROWS_AS(_
= json::parse(std::begin(v
), std::end(v
)), json::parse_error
&);
601 CHECK(!json::accept(std::begin(v
), std::end(v
)));
604 CHECK_NOTHROW(j_error
= json::parse(std::begin(v
), std::end(v
), nullptr, false));
605 CHECK(j_error
.is_discarded());
608 CHECK(!json::sax_parse(std::begin(v
), std::end(v
), &l
));
609 CHECK(l
.events
.size() == 1);
610 CHECK(l
.events
== std::vector
<std::string
>({"parse_error(18)"}));
615 std::array
<std::uint8_t, 17> v
= {{'\"', 'a', 'a', 'a', 'a', 'a', 'a', 'u', '1', '1', '1', '1', '1', '1', '1', '1', '\\'}};
617 CHECK_THROWS_AS(_
= json::parse(std::begin(v
), std::end(v
)), json::parse_error
&);
618 CHECK(!json::accept(std::begin(v
), std::end(v
)));
621 CHECK_NOTHROW(j_error
= json::parse(std::begin(v
), std::end(v
), nullptr, false));
622 CHECK(j_error
.is_discarded());
625 CHECK(!json::sax_parse(std::begin(v
), std::end(v
), &l
));
626 CHECK(l
.events
.size() == 1);
627 CHECK(l
.events
== std::vector
<std::string
>({"parse_error(18)"}));
632 std::array
<std::uint8_t, 3> v
= {{'\"', 0x7F, 0xC1}};
634 CHECK_THROWS_AS(_
= json::parse(std::begin(v
), std::end(v
)), json::parse_error
&);
635 CHECK(!json::accept(std::begin(v
), std::end(v
)));
638 CHECK_NOTHROW(j_error
= json::parse(std::begin(v
), std::end(v
), nullptr, false));
639 CHECK(j_error
.is_discarded());
642 CHECK(!json::sax_parse(std::begin(v
), std::end(v
), &l
));
643 CHECK(l
.events
.size() == 1);
644 CHECK(l
.events
== std::vector
<std::string
>({"parse_error(3)"}));
649 std::array
<std::uint8_t, 4> v
= {{'\"', 0x7F, 0xDF, 0x7F}};
651 CHECK_THROWS_AS(_
= json::parse(std::begin(v
), std::end(v
)), json::parse_error
&);
652 CHECK_THROWS_WITH(_
= json::parse(std::begin(v
), std::end(v
)),
653 "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid string: ill-formed UTF-8 byte; last read: '\"\x7f\xdf\x7f'");
654 CHECK(!json::accept(std::begin(v
), std::end(v
)));
657 CHECK_NOTHROW(j_error
= json::parse(std::begin(v
), std::end(v
), nullptr, false));
658 CHECK(j_error
.is_discarded());
661 CHECK(!json::sax_parse(std::begin(v
), std::end(v
), &l
));
662 CHECK(l
.events
.size() == 1);
663 CHECK(l
.events
== std::vector
<std::string
>({"parse_error(4)"}));
668 std::array
<std::uint8_t, 4> v
= {{'\"', 0x7F, 0xDF, 0xC0}};
670 CHECK_THROWS_AS(_
= json::parse(std::begin(v
), std::end(v
)), json::parse_error
&);
671 CHECK(!json::accept(std::begin(v
), std::end(v
)));
674 CHECK_NOTHROW(j_error
= json::parse(std::begin(v
), std::end(v
), nullptr, false));
675 CHECK(j_error
.is_discarded());
678 CHECK(!json::sax_parse(std::begin(v
), std::end(v
), &l
));
679 CHECK(l
.events
.size() == 1);
680 CHECK(l
.events
== std::vector
<std::string
>({"parse_error(4)"}));
685 std::array
<std::uint8_t, 4> v
= {{'\"', 0x7F, 0xE0, 0x9F}};
687 CHECK_THROWS_AS(_
= json::parse(std::begin(v
), std::end(v
)), json::parse_error
&);
688 CHECK(!json::accept(std::begin(v
), std::end(v
)));
691 CHECK_NOTHROW(j_error
= json::parse(std::begin(v
), std::end(v
), nullptr, false));
692 CHECK(j_error
.is_discarded());
695 CHECK(!json::sax_parse(std::begin(v
), std::end(v
), &l
));
696 CHECK(l
.events
.size() == 1);
697 CHECK(l
.events
== std::vector
<std::string
>({"parse_error(4)"}));
702 std::array
<std::uint8_t, 4> v
= {{'\"', 0x7F, 0xEF, 0xC0}};
704 CHECK_THROWS_AS(_
= json::parse(std::begin(v
), std::end(v
)), json::parse_error
&);
705 CHECK(!json::accept(std::begin(v
), std::end(v
)));
708 CHECK_NOTHROW(j_error
= json::parse(std::begin(v
), std::end(v
), nullptr, false));
709 CHECK(j_error
.is_discarded());
712 CHECK(!json::sax_parse(std::begin(v
), std::end(v
), &l
));
713 CHECK(l
.events
.size() == 1);
714 CHECK(l
.events
== std::vector
<std::string
>({"parse_error(4)"}));
719 std::array
<std::uint8_t, 4> v
= {{'\"', 0x7F, 0xED, 0x7F}};
721 CHECK_THROWS_AS(_
= json::parse(std::begin(v
), std::end(v
)), json::parse_error
&);
722 CHECK(!json::accept(std::begin(v
), std::end(v
)));
725 CHECK_NOTHROW(j_error
= json::parse(std::begin(v
), std::end(v
), nullptr, false));
726 CHECK(j_error
.is_discarded());
729 CHECK(!json::sax_parse(std::begin(v
), std::end(v
), &l
));
730 CHECK(l
.events
.size() == 1);
731 CHECK(l
.events
== std::vector
<std::string
>({"parse_error(4)"}));
736 std::array
<std::uint8_t, 4> v
= {{'\"', 0x7F, 0xF0, 0x8F}};
738 CHECK_THROWS_AS(_
= json::parse(std::begin(v
), std::end(v
)), json::parse_error
&);
739 CHECK(!json::accept(std::begin(v
), std::end(v
)));
742 CHECK_NOTHROW(j_error
= json::parse(std::begin(v
), std::end(v
), nullptr, false));
743 CHECK(j_error
.is_discarded());
746 CHECK(!json::sax_parse(std::begin(v
), std::end(v
), &l
));
747 CHECK(l
.events
.size() == 1);
748 CHECK(l
.events
== std::vector
<std::string
>({"parse_error(4)"}));
753 std::array
<std::uint8_t, 4> v
= {{'\"', 0x7F, 0xF0, 0xC0}};
755 CHECK_THROWS_AS(_
= json::parse(std::begin(v
), std::end(v
)), json::parse_error
&);
756 CHECK(!json::accept(std::begin(v
), std::end(v
)));
759 CHECK_NOTHROW(j_error
= json::parse(std::begin(v
), std::end(v
), nullptr, false));
760 CHECK(j_error
.is_discarded());
763 CHECK(!json::sax_parse(std::begin(v
), std::end(v
), &l
));
764 CHECK(l
.events
.size() == 1);
765 CHECK(l
.events
== std::vector
<std::string
>({"parse_error(4)"}));
770 std::array
<std::uint8_t, 4> v
= {{'\"', 0x7F, 0xF3, 0x7F}};
772 CHECK_THROWS_AS(_
= json::parse(std::begin(v
), std::end(v
)), json::parse_error
&);
773 CHECK(!json::accept(std::begin(v
), std::end(v
)));
776 CHECK_NOTHROW(j_error
= json::parse(std::begin(v
), std::end(v
), nullptr, false));
777 CHECK(j_error
.is_discarded());
780 CHECK(!json::sax_parse(std::begin(v
), std::end(v
), &l
));
781 CHECK(l
.events
.size() == 1);
782 CHECK(l
.events
== std::vector
<std::string
>({"parse_error(4)"}));
787 std::array
<std::uint8_t, 4> v
= {{'\"', 0x7F, 0xF3, 0xC0}};
789 CHECK_THROWS_AS(_
= json::parse(std::begin(v
), std::end(v
)), json::parse_error
&);
790 CHECK(!json::accept(std::begin(v
), std::end(v
)));
793 CHECK_NOTHROW(j_error
= json::parse(std::begin(v
), std::end(v
), nullptr, false));
794 CHECK(j_error
.is_discarded());
797 CHECK(!json::sax_parse(std::begin(v
), std::end(v
), &l
));
798 CHECK(l
.events
.size() == 1);
799 CHECK(l
.events
== std::vector
<std::string
>({"parse_error(4)"}));
804 std::array
<std::uint8_t, 4> v
= {{'\"', 0x7F, 0xF4, 0x7F}};
806 CHECK_THROWS_AS(_
= json::parse(std::begin(v
), std::end(v
)), json::parse_error
&);
807 CHECK(!json::accept(std::begin(v
), std::end(v
)));
810 CHECK_NOTHROW(j_error
= json::parse(std::begin(v
), std::end(v
), nullptr, false));
811 CHECK(j_error
.is_discarded());
814 CHECK(!json::sax_parse(std::begin(v
), std::end(v
), &l
));
815 CHECK(l
.events
.size() == 1);
816 CHECK(l
.events
== std::vector
<std::string
>({"parse_error(4)"}));
821 std::array
<std::uint8_t, 6> v
= {{'{', '\"', '\"', ':', '1', '1'}};
823 CHECK_THROWS_AS(_
= json::parse(std::begin(v
), std::end(v
)), json::parse_error
&);
824 CHECK(!json::accept(std::begin(v
), std::end(v
)));
827 CHECK_NOTHROW(j_error
= json::parse(std::begin(v
), std::end(v
), nullptr, false));
828 CHECK(j_error
.is_discarded());
831 CHECK(!json::sax_parse(std::begin(v
), std::end(v
), &l
));
832 CHECK(l
.events
.size() == 4);
833 CHECK(l
.events
== std::vector
<std::string
>(
835 "start_object()", "key()", "number_unsigned(11)",
842 SECTION("ignoring byte-order marks")
844 std::string bom
= "\xEF\xBB\xBF";
849 CHECK_THROWS_AS(_
= json::parse(bom
), json::parse_error
&);
850 CHECK_THROWS_WITH(_
= json::parse(bom
),
851 "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal");
853 CHECK_THROWS_AS(_
= json::parse(std::istringstream(bom
)), json::parse_error
&);
854 CHECK_THROWS_WITH(_
= json::parse(std::istringstream(bom
)),
855 "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal");
858 CHECK(!json::sax_parse(bom
, &l
));
859 CHECK(l
.events
.size() == 1);
860 CHECK(l
.events
== std::vector
<std::string
>(
866 SECTION("BOM and content")
868 CHECK(json::parse(bom
+ "1") == 1);
869 CHECK(json::parse(std::istringstream(bom
+ "1")) == 1);
873 CHECK(json::sax_parse(std::istringstream(bom
+ "1"), &l1
));
874 CHECK(json::sax_parse(bom
+ "1", &l2
));
875 CHECK(l1
.events
.size() == 1);
876 CHECK(l1
.events
== std::vector
<std::string
>(
880 CHECK(l2
.events
.size() == 1);
881 CHECK(l2
.events
== std::vector
<std::string
>(
887 SECTION("2 byte of BOM")
890 CHECK_THROWS_AS(_
= json::parse(bom
.substr(0, 2)), json::parse_error
&);
891 CHECK_THROWS_WITH(_
= json::parse(bom
.substr(0, 2)),
892 "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid BOM; must be 0xEF 0xBB 0xBF if given; last read: '\xEF\xBB'");
894 CHECK_THROWS_AS(_
= json::parse(std::istringstream(bom
.substr(0, 2))), json::parse_error
&);
895 CHECK_THROWS_WITH(_
= json::parse(std::istringstream(bom
.substr(0, 2))),
896 "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid BOM; must be 0xEF 0xBB 0xBF if given; last read: '\xEF\xBB'");
900 CHECK(!json::sax_parse(std::istringstream(bom
.substr(0, 2)), &l1
));
901 CHECK(!json::sax_parse(bom
.substr(0, 2), &l2
));
902 CHECK(l1
.events
.size() == 1);
903 CHECK(l1
.events
== std::vector
<std::string
>(
907 CHECK(l2
.events
.size() == 1);
908 CHECK(l2
.events
== std::vector
<std::string
>(
914 SECTION("1 byte of BOM")
917 CHECK_THROWS_AS(_
= json::parse(bom
.substr(0, 1)), json::parse_error
&);
918 CHECK_THROWS_WITH(_
= json::parse(bom
.substr(0, 1)),
919 "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid BOM; must be 0xEF 0xBB 0xBF if given; last read: '\xEF'");
921 CHECK_THROWS_AS(_
= json::parse(std::istringstream(bom
.substr(0, 1))), json::parse_error
&);
922 CHECK_THROWS_WITH(_
= json::parse(std::istringstream(bom
.substr(0, 1))),
923 "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid BOM; must be 0xEF 0xBB 0xBF if given; last read: '\xEF'");
927 CHECK(!json::sax_parse(std::istringstream(bom
.substr(0, 1)), &l1
));
928 CHECK(!json::sax_parse(bom
.substr(0, 1), &l2
));
929 CHECK(l1
.events
.size() == 1);
930 CHECK(l1
.events
== std::vector
<std::string
>(
934 CHECK(l2
.events
.size() == 1);
935 CHECK(l2
.events
== std::vector
<std::string
>(
941 SECTION("variations")
943 // calculate variations of each byte of the BOM to make sure
944 // that the BOM and only the BOM is skipped
945 for (int i0
= -1; i0
< 2; ++i0
)
947 for (int i1
= -1; i1
< 2; ++i1
)
949 for (int i2
= -1; i2
< 2; ++i2
)
951 // debug output for the variations
957 s
.push_back(static_cast<char>(bom
[0] + i0
));
958 s
.push_back(static_cast<char>(bom
[1] + i1
));
959 s
.push_back(static_cast<char>(bom
[2] + i2
));
961 if (i0
== 0 && i1
== 0 && i2
== 0)
963 // without any variation, we skip the BOM
964 CHECK(json::parse(s
+ "null") == json());
965 CHECK(json::parse(std::istringstream(s
+ "null")) == json());
968 CHECK(json::sax_parse(s
+ "null", &l
));
969 CHECK(l
.events
.size() == 1);
970 CHECK(l
.events
== std::vector
<std::string
>(
977 // any variation is an error
979 CHECK_THROWS_AS(_
= json::parse(s
+ "null"), json::parse_error
&);
980 CHECK_THROWS_AS(_
= json::parse(std::istringstream(s
+ "null")), json::parse_error
&);
983 CHECK(!json::sax_parse(s
+ "null", &l
));
984 CHECK(l
.events
.size() == 1);
988 CHECK(l
.events
== std::vector
<std::string
>(
995 CHECK(l
.events
== std::vector
<std::string
>(
1002 CHECK(l
.events
== std::vector
<std::string
>(
1013 SECTION("preserve state after parsing")
1015 std::istringstream
s(bom
+ "123 456");
1024 SECTION("SAX and early abort")
1026 std::string s
= R
"([1, ["string
", 43.12], null, {"key1
": true, "key2
": false}])";
1028 SaxEventLogger default_logger
;
1029 SaxEventLoggerExitAfterStartObject exit_after_start_object
;
1030 SaxEventLoggerExitAfterKey exit_after_key
;
1031 SaxEventLoggerExitAfterStartArray exit_after_start_array
;
1033 json::sax_parse(s
, &default_logger
);
1034 CHECK(default_logger
.events
.size() == 14);
1035 CHECK(default_logger
.events
== std::vector
<std::string
>(
1037 "start_array()", "number_unsigned(1)", "start_array()",
1038 "string(string)", "number_float(43.12)", "end_array()", "null()",
1039 "start_object()", "key(key1)", "boolean(true)", "key(key2)",
1040 "boolean(false)", "end_object()", "end_array()"
1043 json::sax_parse(s
, &exit_after_start_object
);
1044 CHECK(exit_after_start_object
.events
.size() == 8);
1045 CHECK(exit_after_start_object
.events
== std::vector
<std::string
>(
1047 "start_array()", "number_unsigned(1)", "start_array()",
1048 "string(string)", "number_float(43.12)", "end_array()", "null()",
1052 json::sax_parse(s
, &exit_after_key
);
1053 CHECK(exit_after_key
.events
.size() == 9);
1054 CHECK(exit_after_key
.events
== std::vector
<std::string
>(
1056 "start_array()", "number_unsigned(1)", "start_array()",
1057 "string(string)", "number_float(43.12)", "end_array()", "null()",
1058 "start_object()", "key(key1)"
1061 json::sax_parse(s
, &exit_after_start_array
);
1062 CHECK(exit_after_start_array
.events
.size() == 1);
1063 CHECK(exit_after_start_array
.events
== std::vector
<std::string
>(
1070 TEST_CASE_TEMPLATE("deserialization of different character types (ASCII)", T
,
1071 char, unsigned char, signed char,
1074 std::uint8_t, std::int8_t,
1075 std::int16_t, std::uint16_t,
1076 std::int32_t, std::uint32_t)
1078 std::vector
<T
> v
= {'t', 'r', 'u', 'e'};
1079 CHECK(json::parse(v
) == json(true));
1080 CHECK(json::accept(v
));
1083 CHECK(json::sax_parse(v
, &l
));
1084 CHECK(l
.events
.size() == 1);
1085 CHECK(l
.events
== std::vector
<std::string
>({"boolean(true)"}));
1088 TEST_CASE_TEMPLATE("deserialization of different character types (UTF-8)", T
,
1089 char, unsigned char, std::uint8_t)
1092 std::vector
<T
> v
= {'"', static_cast<T
>(0xe2u
), static_cast<T
>(0xadu
), static_cast<T
>(0x90u
), static_cast<T
>(0xefu
), static_cast<T
>(0xb8u
), static_cast<T
>(0x8fu
), '"'};
1093 CHECK(json::parse(v
).dump(-1, ' ', true) == "\"\\u2b50\\ufe0f\"");
1094 CHECK(json::accept(v
));
1097 CHECK(json::sax_parse(v
, &l
));
1098 CHECK(l
.events
.size() == 1);
1101 TEST_CASE_TEMPLATE("deserialization of different character types (UTF-16)", T
,
1102 char16_t
, std::uint16_t)
1105 std::vector
<T
> v
= {static_cast<T
>('"'), static_cast<T
>(0x2b50), static_cast<T
>(0xfe0f), static_cast<T
>('"')};
1106 CHECK(json::parse(v
).dump(-1, ' ', true) == "\"\\u2b50\\ufe0f\"");
1107 CHECK(json::accept(v
));
1110 CHECK(json::sax_parse(v
, &l
));
1111 CHECK(l
.events
.size() == 1);
1114 TEST_CASE_TEMPLATE("deserialization of different character types (UTF-32)", T
,
1115 char32_t
, std::uint32_t)
1118 std::vector
<T
> v
= {static_cast<T
>('"'), static_cast<T
>(0x2b50), static_cast<T
>(0xfe0f), static_cast<T
>('"')};
1119 CHECK(json::parse(v
).dump(-1, ' ', true) == "\"\\u2b50\\ufe0f\"");
1120 CHECK(json::accept(v
));
1123 CHECK(json::sax_parse(v
, &l
));
1124 CHECK(l
.events
.size() == 1);