1//     __ _____ _____ _____
2//  __|  |   __|     |   | |  JSON for Modern C++ (supporting code)
3// |  |  |__   |  |  | | | |  version 3.11.2
4// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
5//
6// Copyright (c) 2013-2022 Niels Lohmann <http://nlohmann.me>.
7// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
8// SPDX-License-Identifier: MIT
9
10// cmake/test.cmake selects the C++ standard versions with which to build a
11// unit test based on the presence of JSON_HAS_CPP_<VERSION> macros.
12// When using macros that are only defined for particular versions of the standard
13// (e.g., JSON_HAS_FILESYSTEM for C++17 and up), please mention the corresponding
14// version macro in a comment close by, like this:
15// JSON_HAS_CPP_<VERSION> (do not remove; see note at top of file)
16
17#include "doctest_compatibility.h"
18
19#define JSON_TESTS_PRIVATE
20#include <nlohmann/json.hpp>
21using nlohmann::json;
22
23#include <deque>
24#include <forward_list>
25#include <list>
26#include <set>
27#include <unordered_map>
28#include <unordered_set>
29#include <valarray>
30
31// NLOHMANN_JSON_SERIALIZE_ENUM uses a static std::pair
32DOCTEST_CLANG_SUPPRESS_WARNING_PUSH
33DOCTEST_CLANG_SUPPRESS_WARNING("-Wexit-time-destructors")
34
35TEST_CASE("value conversion")
36{
37    SECTION("get an object (explicit)")
38    {
39        json::object_t o_reference = {{"object", json::object()},
40            {"array", {1, 2, 3, 4}},
41            {"number", 42},
42            {"boolean", false},
43            {"null", nullptr},
44            {"string", "Hello world"}
45        };
46        json j(o_reference);
47
48        SECTION("json::object_t")
49        {
50            json::object_t o = j.get<json::object_t>();
51            CHECK(json(o) == j);
52        }
53
54        SECTION("std::map<json::string_t, json>")
55        {
56            std::map<json::string_t, json> o =
57                j.get<std::map<json::string_t, json>>();
58            CHECK(json(o) == j);
59        }
60
61        SECTION("std::multimap<json::string_t, json>")
62        {
63            std::multimap<json::string_t, json> o =
64                j.get<std::multimap<json::string_t, json>>();
65            CHECK(json(o) == j);
66        }
67
68        SECTION("std::unordered_map<json::string_t, json>")
69        {
70            std::unordered_map<json::string_t, json> o =
71                j.get<std::unordered_map<json::string_t, json>>();
72            CHECK(json(o) == j);
73        }
74
75        SECTION("std::unordered_multimap<json::string_t, json>")
76        {
77            std::unordered_multimap<json::string_t, json> o =
78                j.get<std::unordered_multimap<json::string_t, json>>();
79            CHECK(json(o) == j);
80        }
81
82        SECTION("exception in case of a non-object type")
83        {
84            CHECK_THROWS_WITH_AS(
85                json(json::value_t::null).get<json::object_t>(),
86                "[json.exception.type_error.302] type must be object, but is null", json::type_error&);
87            CHECK_THROWS_WITH_AS(
88                json(json::value_t::array).get<json::object_t>(),
89                "[json.exception.type_error.302] type must be object, but is array", json::type_error&);
90            CHECK_THROWS_WITH_AS(
91                json(json::value_t::string).get<json::object_t>(),
92                "[json.exception.type_error.302] type must be object, but is string", json::type_error&);
93            CHECK_THROWS_WITH_AS(json(json::value_t::boolean).get<json::object_t>(),
94                                 "[json.exception.type_error.302] type must be object, "
95                                 "but is boolean", json::type_error&);
96            CHECK_THROWS_WITH_AS(
97                json(json::value_t::number_integer).get<json::object_t>(),
98                "[json.exception.type_error.302] type must be object, but is number", json::type_error&);
99            CHECK_THROWS_WITH_AS(
100                json(json::value_t::number_unsigned).get<json::object_t>(),
101                "[json.exception.type_error.302] type must be object, but is number", json::type_error&);
102            CHECK_THROWS_WITH_AS(
103                json(json::value_t::number_float).get<json::object_t>(),
104                "[json.exception.type_error.302] type must be object, but is number", json::type_error&);
105        }
106    }
107
108    SECTION("get an object (explicit, get_to)")
109    {
110        json::object_t o_reference = {{"object", json::object()},
111            {"array", {1, 2, 3, 4}},
112            {"number", 42},
113            {"boolean", false},
114            {"null", nullptr},
115            {"string", "Hello world"}
116        };
117        json j(o_reference);
118
119        SECTION("json::object_t")
120        {
121            json::object_t o = {{"previous", "value"}};
122            j.get_to(o);
123            CHECK(json(o) == j);
124        }
125
126        SECTION("std::map<json::string_t, json>")
127        {
128            std::map<json::string_t, json> o{{"previous", "value"}};
129            j.get_to(o);
130            CHECK(json(o) == j);
131        }
132
133        SECTION("std::multimap<json::string_t, json>")
134        {
135            std::multimap<json::string_t, json> o{{"previous", "value"}};
136            j.get_to(o);
137            CHECK(json(o) == j);
138        }
139
140        SECTION("std::unordered_map<json::string_t, json>")
141        {
142            std::unordered_map<json::string_t, json> o{{"previous", "value"}};
143            j.get_to(o);
144            CHECK(json(o) == j);
145        }
146
147        SECTION("std::unordered_multimap<json::string_t, json>")
148        {
149            std::unordered_multimap<json::string_t, json> o{{"previous", "value"}};
150            j.get_to(o);
151            CHECK(json(o) == j);
152        }
153    }
154
155#if JSON_USE_IMPLICIT_CONVERSIONS
156    SECTION("get an object (implicit)")
157    {
158        json::object_t o_reference = {{"object", json::object()},
159            {"array", {1, 2, 3, 4}},
160            {"number", 42},
161            {"boolean", false},
162            {"null", nullptr},
163            {"string", "Hello world"}
164        };
165        json j(o_reference);
166
167        SECTION("json::object_t")
168        {
169            json::object_t o = j;
170            CHECK(json(o) == j);
171        }
172
173        SECTION("std::map<json::string_t, json>")
174        {
175            std::map<json::string_t, json> o = j;
176            CHECK(json(o) == j);
177        }
178
179        SECTION("std::multimap<json::string_t, json>")
180        {
181            std::multimap<json::string_t, json> o = j;
182            CHECK(json(o) == j);
183        }
184
185        SECTION("std::unordered_map<json::string_t, json>")
186        {
187            std::unordered_map<json::string_t, json> o = j;
188            CHECK(json(o) == j);
189        }
190
191        SECTION("std::unordered_multimap<json::string_t, json>")
192        {
193            std::unordered_multimap<json::string_t, json> o = j;
194            CHECK(json(o) == j);
195        }
196    }
197#endif
198
199    SECTION("get an array (explicit)")
200    {
201        json::array_t a_reference{json(1),     json(1u),       json(2.2),
202                                  json(false), json("string"), json()};
203        json j(a_reference);
204
205        SECTION("json::array_t")
206        {
207            json::array_t a = j.get<json::array_t>();
208            CHECK(json(a) == j);
209        }
210
211        SECTION("std::list<json>")
212        {
213            std::list<json> a = j.get<std::list<json>>();
214            CHECK(json(a) == j);
215        }
216
217        SECTION("std::forward_list<json>")
218        {
219            std::forward_list<json> a = j.get<std::forward_list<json>>();
220            CHECK(json(a) == j);
221
222            CHECK_THROWS_WITH_AS(
223                json(json::value_t::null).get<std::forward_list<json>>(),
224                "[json.exception.type_error.302] type must be array, but is null", json::type_error&);
225        }
226
227        SECTION("std::vector<json>")
228        {
229            std::vector<json> a = j.get<std::vector<json>>();
230            CHECK(json(a) == j);
231
232            CHECK_THROWS_WITH_AS(
233                json(json::value_t::null).get<std::vector<json>>(),
234                "[json.exception.type_error.302] type must be array, but is null", json::type_error&);
235
236#if !defined(JSON_NOEXCEPTION)
237            SECTION("reserve is called on containers that supports it")
238            {
239                // make sure all values are properly copied
240                json j2({1, 2, 3, 4, 5, 6, 7, 8, 9, 10});
241                auto v2 = j2.get<std::vector<int>>();
242                CHECK(v2.size() == 10);
243            }
244#endif
245        }
246
247        SECTION("built-in arrays")
248        {
249            const char str[] = "a string"; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
250            const int nbs[] = {0, 1, 2}; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
251
252            json j2 = nbs;
253            json j3 = str;
254
255            auto v = j2.get<std::vector<int>>();
256            auto s = j3.get<std::string>();
257            CHECK(std::equal(v.begin(), v.end(), std::begin(nbs)));
258            CHECK(s == str);
259        }
260
261        SECTION("std::deque<json>")
262        {
263            std::deque<json> a = j.get<std::deque<json>>();
264            CHECK(json(a) == j);
265        }
266
267        SECTION("exception in case of a non-array type")
268        {
269            CHECK_THROWS_WITH_AS(
270                json(json::value_t::object).get<std::vector<int>>(),
271                "[json.exception.type_error.302] type must be array, but is object", json::type_error&);
272            CHECK_THROWS_WITH_AS(
273                json(json::value_t::null).get<json::array_t>(),
274                "[json.exception.type_error.302] type must be array, but is null", json::type_error&);
275            CHECK_THROWS_WITH_AS(
276                json(json::value_t::object).get<json::array_t>(),
277                "[json.exception.type_error.302] type must be array, but is object", json::type_error&);
278            CHECK_THROWS_WITH_AS(
279                json(json::value_t::string).get<json::array_t>(),
280                "[json.exception.type_error.302] type must be array, but is string", json::type_error&);
281            CHECK_THROWS_WITH_AS(
282                json(json::value_t::boolean).get<json::array_t>(),
283                "[json.exception.type_error.302] type must be array, but is boolean", json::type_error&);
284            CHECK_THROWS_WITH_AS(
285                json(json::value_t::number_integer).get<json::array_t>(),
286                "[json.exception.type_error.302] type must be array, but is number", json::type_error&);
287            CHECK_THROWS_WITH_AS(
288                json(json::value_t::number_unsigned).get<json::array_t>(),
289                "[json.exception.type_error.302] type must be array, but is number", json::type_error&);
290            CHECK_THROWS_WITH_AS(
291                json(json::value_t::number_float).get<json::array_t>(),
292                "[json.exception.type_error.302] type must be array, but is number", json::type_error&);
293        }
294    }
295
296    SECTION("get an array (explicit, get_to)")
297    {
298        json::array_t a_reference{json(1),     json(1u),       json(2.2),
299                                  json(false), json("string"), json()};
300        json j(a_reference);
301
302        SECTION("json::array_t")
303        {
304            json::array_t a{"previous", "value"};
305            j.get_to(a);
306            CHECK(json(a) == j);
307        }
308
309        SECTION("std::valarray<json>")
310        {
311            std::valarray<json> a{"previous", "value"};
312            j.get_to(a);
313            CHECK(json(a) == j);
314        }
315
316        SECTION("std::list<json>")
317        {
318            std::list<json> a{"previous", "value"};
319            j.get_to(a);
320            CHECK(json(a) == j);
321        }
322
323        SECTION("std::forward_list<json>")
324        {
325            std::forward_list<json> a{"previous", "value"};
326            j.get_to(a);
327            CHECK(json(a) == j);
328        }
329
330        SECTION("std::vector<json>")
331        {
332            std::vector<json> a{"previous", "value"};
333            j.get_to(a);
334            CHECK(json(a) == j);
335        }
336
337        SECTION("built-in arrays")
338        {
339            const int nbs[] = {0, 1, 2}; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
340            int nbs2[] = {0, 0, 0}; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
341
342            json j2 = nbs;
343            j2.get_to(nbs2);
344            CHECK(std::equal(std::begin(nbs), std::end(nbs), std::begin(nbs2)));
345        }
346
347        SECTION("std::deque<json>")
348        {
349            std::deque<json> a{"previous", "value"};
350            j.get_to(a);
351            CHECK(json(a) == j);
352        }
353    }
354
355#if JSON_USE_IMPLICIT_CONVERSIONS
356    SECTION("get an array (implicit)")
357    {
358        json::array_t a_reference{json(1),     json(1u),       json(2.2),
359                                  json(false), json("string"), json()};
360        json j(a_reference);
361
362        SECTION("json::array_t")
363        {
364            json::array_t a = j;
365            CHECK(json(a) == j);
366        }
367
368        SECTION("std::list<json>")
369        {
370            std::list<json> a = j;
371            CHECK(json(a) == j);
372        }
373
374        SECTION("std::forward_list<json>")
375        {
376            std::forward_list<json> a = j;
377            CHECK(json(a) == j);
378        }
379
380        SECTION("std::vector<json>")
381        {
382            std::vector<json> a = j;
383            CHECK(json(a) == j);
384        }
385
386        SECTION("std::deque<json>")
387        {
388            std::deque<json> a = j;
389            CHECK(json(a) == j);
390        }
391    }
392#endif
393
394    SECTION("get a string (explicit)")
395    {
396        json::string_t s_reference{"Hello world"};
397        json j(s_reference);
398
399        SECTION("string_t")
400        {
401            json::string_t s = j.get<json::string_t>();
402            CHECK(json(s) == j);
403        }
404
405        SECTION("std::string")
406        {
407            std::string s = j.get<std::string>();
408            CHECK(json(s) == j);
409        }
410#if defined(JSON_HAS_CPP_17)
411        SECTION("std::string_view")
412        {
413            std::string_view s = j.get<std::string_view>();
414            CHECK(json(s) == j);
415        }
416#endif
417
418        SECTION("exception in case of a non-string type")
419        {
420            CHECK_THROWS_WITH_AS(
421                json(json::value_t::null).get<json::string_t>(),
422                "[json.exception.type_error.302] type must be string, but is null", json::type_error&);
423            CHECK_THROWS_WITH_AS(
424                json(json::value_t::object).get<json::string_t>(),
425                "[json.exception.type_error.302] type must be string, but is object", json::type_error&);
426            CHECK_THROWS_WITH_AS(
427                json(json::value_t::array).get<json::string_t>(),
428                "[json.exception.type_error.302] type must be string, but is array", json::type_error&);
429            CHECK_THROWS_WITH_AS(json(json::value_t::boolean).get<json::string_t>(),
430                                 "[json.exception.type_error.302] type must be string, "
431                                 "but is boolean", json::type_error&);
432            CHECK_THROWS_WITH_AS(
433                json(json::value_t::number_integer).get<json::string_t>(),
434                "[json.exception.type_error.302] type must be string, but is number", json::type_error&);
435            CHECK_THROWS_WITH_AS(
436                json(json::value_t::number_unsigned).get<json::string_t>(),
437                "[json.exception.type_error.302] type must be string, but is number", json::type_error&);
438            CHECK_THROWS_WITH_AS(
439                json(json::value_t::number_float).get<json::string_t>(),
440                "[json.exception.type_error.302] type must be string, but is number", json::type_error&);
441        }
442
443#if defined(JSON_HAS_CPP_17)
444        SECTION("exception in case of a non-string type using string_view")
445        {
446            CHECK_THROWS_WITH_AS(json(json::value_t::null).get<std::string_view>(),
447                                 "[json.exception.type_error.302] type must be string, but is null", json::type_error&);
448            CHECK_THROWS_WITH_AS(json(json::value_t::object).get<std::string_view>(),
449                                 "[json.exception.type_error.302] type must be string, but is object", json::type_error&);
450            CHECK_THROWS_WITH_AS(json(json::value_t::array).get<std::string_view>(),
451                                 "[json.exception.type_error.302] type must be string, but is array", json::type_error&);
452            CHECK_THROWS_WITH_AS(json(json::value_t::boolean).get<std::string_view>(),
453                                 "[json.exception.type_error.302] type must be string, but is boolean", json::type_error&);
454            CHECK_THROWS_WITH_AS(json(json::value_t::number_integer).get<std::string_view>(),
455                                 "[json.exception.type_error.302] type must be string, but is number", json::type_error&);
456            CHECK_THROWS_WITH_AS(json(json::value_t::number_unsigned).get<std::string_view>(),
457                                 "[json.exception.type_error.302] type must be string, but is number", json::type_error&);
458            CHECK_THROWS_WITH_AS(json(json::value_t::number_float).get<std::string_view>(),
459                                 "[json.exception.type_error.302] type must be string, but is number", json::type_error&);
460        }
461#endif
462    }
463
464    SECTION("get a string (explicit, get_to)")
465    {
466        json::string_t s_reference{"Hello world"};
467        json j(s_reference);
468
469        SECTION("string_t")
470        {
471            json::string_t s = "previous value";
472            j.get_to(s);
473            CHECK(json(s) == j);
474        }
475
476        SECTION("std::string")
477        {
478            std::string s = "previous value";
479            j.get_to(s);
480            CHECK(json(s) == j);
481        }
482#if defined(JSON_HAS_CPP_17)
483        SECTION("std::string_view")
484        {
485            std::string s = "previous value";
486            std::string_view sv = s;
487            j.get_to(sv);
488            CHECK(json(sv) == j);
489        }
490#endif
491    }
492
493    SECTION("get null (explicit)")
494    {
495        std::nullptr_t n = nullptr;
496        json j(n);
497
498        auto n2 = j.get<std::nullptr_t>();
499        CHECK(n2 == n);
500
501        CHECK_THROWS_WITH_AS(json(json::value_t::string).get<std::nullptr_t>(),
502                             "[json.exception.type_error.302] type must be null, but is string", json::type_error&);
503        CHECK_THROWS_WITH_AS(json(json::value_t::object).get<std::nullptr_t>(),
504                             "[json.exception.type_error.302] type must be null, but is object", json::type_error&);
505        CHECK_THROWS_WITH_AS(json(json::value_t::array).get<std::nullptr_t>(),
506                             "[json.exception.type_error.302] type must be null, but is array", json::type_error&);
507        CHECK_THROWS_WITH_AS(json(json::value_t::boolean).get<std::nullptr_t>(),
508                             "[json.exception.type_error.302] type must be null, but is boolean", json::type_error&);
509        CHECK_THROWS_WITH_AS(json(json::value_t::number_integer).get<std::nullptr_t>(),
510                             "[json.exception.type_error.302] type must be null, but is number", json::type_error&);
511        CHECK_THROWS_WITH_AS(json(json::value_t::number_unsigned).get<std::nullptr_t>(),
512                             "[json.exception.type_error.302] type must be null, but is number", json::type_error&);
513        CHECK_THROWS_WITH_AS(json(json::value_t::number_float).get<std::nullptr_t>(),
514                             "[json.exception.type_error.302] type must be null, but is number", json::type_error&);
515    }
516
517#if JSON_USE_IMPLICIT_CONVERSIONS
518    SECTION("get a string (implicit)")
519    {
520        json::string_t s_reference{"Hello world"};
521        json j(s_reference);
522
523        SECTION("string_t")
524        {
525            json::string_t s = j;
526            CHECK(json(s) == j);
527        }
528
529#if defined(JSON_HAS_CPP_17)
530        SECTION("std::string_view")
531        {
532            std::string_view s = j.get<std::string_view>();
533            CHECK(json(s) == j);
534        }
535#endif
536
537        SECTION("std::string")
538        {
539            std::string s = j;
540            CHECK(json(s) == j);
541        }
542    }
543#endif
544
545    SECTION("get a boolean (explicit)")
546    {
547        json::boolean_t b_reference{true};
548        json j(b_reference);
549
550        SECTION("boolean_t")
551        {
552            auto b = j.get<json::boolean_t>();
553            CHECK(json(b) == j);
554        }
555
556        SECTION("uint8_t")
557        {
558            auto n = j.get<uint8_t>();
559            CHECK(n == 1);
560        }
561
562        SECTION("bool")
563        {
564            bool b = j.get<bool>();
565            CHECK(json(b) == j);
566        }
567
568        SECTION("exception in case of a non-number type")
569        {
570            CHECK_THROWS_AS(json(json::value_t::string).get<uint8_t>(),
571                            json::type_error&);
572
573            CHECK_THROWS_WITH_AS(
574                json(json::value_t::null).get<json::boolean_t>(),
575                "[json.exception.type_error.302] type must be boolean, but is null", json::type_error&);
576            CHECK_THROWS_WITH_AS(json(json::value_t::object).get<json::boolean_t>(),
577                                 "[json.exception.type_error.302] type must be boolean, "
578                                 "but is object", json::type_error&);
579            CHECK_THROWS_WITH_AS(
580                json(json::value_t::array).get<json::boolean_t>(),
581                "[json.exception.type_error.302] type must be boolean, but is array", json::type_error&);
582            CHECK_THROWS_WITH_AS(json(json::value_t::string).get<json::boolean_t>(),
583                                 "[json.exception.type_error.302] type must be boolean, "
584                                 "but is string", json::type_error&);
585            CHECK_THROWS_WITH_AS(
586                json(json::value_t::number_integer).get<json::boolean_t>(),
587                "[json.exception.type_error.302] type must be boolean, but is "
588                "number", json::type_error&);
589            CHECK_THROWS_WITH_AS(
590                json(json::value_t::number_unsigned).get<json::boolean_t>(),
591                "[json.exception.type_error.302] type must be boolean, but is "
592                "number", json::type_error&);
593            CHECK_THROWS_WITH_AS(
594                json(json::value_t::number_float).get<json::boolean_t>(),
595                "[json.exception.type_error.302] type must be boolean, but is "
596                "number", json::type_error&);
597        }
598    }
599
600#if JSON_USE_IMPLICIT_CONVERSIONS
601    SECTION("get a boolean (implicit)")
602    {
603        json::boolean_t b_reference{true};
604        json j(b_reference);
605
606        SECTION("boolean_t")
607        {
608            json::boolean_t b = j;
609            CHECK(json(b) == j);
610        }
611
612        SECTION("bool")
613        {
614            bool b = j;
615            CHECK(json(b) == j);
616        }
617    }
618#endif
619
620    SECTION("get an integer number (explicit)")
621    {
622        json::number_integer_t n_reference{42};
623        json j(n_reference);
624        json::number_unsigned_t n_unsigned_reference{42u};
625        json j_unsigned(n_unsigned_reference);
626
627        SECTION("number_integer_t")
628        {
629            auto n = j.get<json::number_integer_t>();
630            CHECK(json(n) == j);
631        }
632
633        SECTION("number_unsigned_t")
634        {
635            auto n = j_unsigned.get<json::number_unsigned_t>();
636            CHECK(json(n) == j_unsigned);
637        }
638
639        SECTION("short")
640        {
641            auto n = j.get<short>();
642            CHECK(json(n) == j);
643        }
644
645        SECTION("unsigned short")
646        {
647            auto n = j.get<unsigned short>();
648            CHECK(json(n) == j);
649        }
650
651        SECTION("int")
652        {
653            int n = j.get<int>();
654            CHECK(json(n) == j);
655        }
656
657        SECTION("unsigned int")
658        {
659            auto n = j.get<unsigned int>();
660            CHECK(json(n) == j);
661        }
662
663        SECTION("long")
664        {
665            long n = j.get<long>();
666            CHECK(json(n) == j);
667        }
668
669        SECTION("unsigned long")
670        {
671            auto n = j.get<unsigned long>();
672            CHECK(json(n) == j);
673        }
674
675        SECTION("long long")
676        {
677            auto n = j.get<long long>();
678            CHECK(json(n) == j);
679        }
680
681        SECTION("unsigned long long")
682        {
683            auto n = j.get<unsigned long long>();
684            CHECK(json(n) == j);
685        }
686
687        SECTION("int8_t")
688        {
689            auto n = j.get<int8_t>();
690            CHECK(json(n) == j);
691        }
692
693        SECTION("int16_t")
694        {
695            auto n = j.get<int16_t>();
696            CHECK(json(n) == j);
697        }
698
699        SECTION("int32_t")
700        {
701            auto n = j.get<int32_t>();
702            CHECK(json(n) == j);
703        }
704
705        SECTION("int64_t")
706        {
707            auto n = j.get<int64_t>();
708            CHECK(json(n) == j);
709        }
710
711        SECTION("int8_fast_t")
712        {
713            auto n = j.get<int_fast8_t>();
714            CHECK(json(n) == j);
715        }
716
717        SECTION("int16_fast_t")
718        {
719            auto n = j.get<int_fast16_t>();
720            CHECK(json(n) == j);
721        }
722
723        SECTION("int32_fast_t")
724        {
725            auto n = j.get<int_fast32_t>();
726            CHECK(json(n) == j);
727        }
728
729        SECTION("int64_fast_t")
730        {
731            auto n = j.get<int_fast64_t>();
732            CHECK(json(n) == j);
733        }
734
735        SECTION("int8_least_t")
736        {
737            auto n = j.get<int_least8_t>();
738            CHECK(json(n) == j);
739        }
740
741        SECTION("int16_least_t")
742        {
743            auto n = j.get<int_least16_t>();
744            CHECK(json(n) == j);
745        }
746
747        SECTION("int32_least_t")
748        {
749            auto n = j.get<int_least32_t>();
750            CHECK(json(n) == j);
751        }
752
753        SECTION("int64_least_t")
754        {
755            auto n = j.get<int_least64_t>();
756            CHECK(json(n) == j);
757        }
758
759        SECTION("uint8_t")
760        {
761            auto n = j.get<uint8_t>();
762            CHECK(json(n) == j);
763        }
764
765        SECTION("uint16_t")
766        {
767            auto n = j.get<uint16_t>();
768            CHECK(json(n) == j);
769        }
770
771        SECTION("uint32_t")
772        {
773            auto n = j.get<uint32_t>();
774            CHECK(json(n) == j);
775        }
776
777        SECTION("uint64_t")
778        {
779            auto n = j.get<uint64_t>();
780            CHECK(json(n) == j);
781        }
782
783        SECTION("uint8_fast_t")
784        {
785            auto n = j.get<uint_fast8_t>();
786            CHECK(json(n) == j);
787        }
788
789        SECTION("uint16_fast_t")
790        {
791            auto n = j.get<uint_fast16_t>();
792            CHECK(json(n) == j);
793        }
794
795        SECTION("uint32_fast_t")
796        {
797            auto n = j.get<uint_fast32_t>();
798            CHECK(json(n) == j);
799        }
800
801        SECTION("uint64_fast_t")
802        {
803            auto n = j.get<uint_fast64_t>();
804            CHECK(json(n) == j);
805        }
806
807        SECTION("uint8_least_t")
808        {
809            auto n = j.get<uint_least8_t>();
810            CHECK(json(n) == j);
811        }
812
813        SECTION("uint16_least_t")
814        {
815            auto n = j.get<uint_least16_t>();
816            CHECK(json(n) == j);
817        }
818
819        SECTION("uint32_least_t")
820        {
821            auto n = j.get<uint_least32_t>();
822            CHECK(json(n) == j);
823        }
824
825        SECTION("uint64_least_t")
826        {
827            auto n = j.get<uint_least64_t>();
828            CHECK(json(n) == j);
829        }
830
831        SECTION("exception in case of a non-number type")
832        {
833            CHECK_THROWS_WITH_AS(
834                json(json::value_t::null).get<json::number_integer_t>(),
835                "[json.exception.type_error.302] type must be number, but is null", json::type_error&);
836            CHECK_THROWS_WITH_AS(
837                json(json::value_t::object).get<json::number_integer_t>(),
838                "[json.exception.type_error.302] type must be number, but is object", json::type_error&);
839            CHECK_THROWS_WITH_AS(
840                json(json::value_t::array).get<json::number_integer_t>(),
841                "[json.exception.type_error.302] type must be number, but is array", json::type_error&);
842            CHECK_THROWS_WITH_AS(
843                json(json::value_t::string).get<json::number_integer_t>(),
844                "[json.exception.type_error.302] type must be number, but is string", json::type_error&);
845            CHECK_THROWS_WITH_AS(
846                json(json::value_t::boolean).get<json::number_integer_t>(),
847                "[json.exception.type_error.302] type must be number, but is "
848                "boolean", json::type_error&);
849
850            CHECK_NOTHROW(
851                json(json::value_t::number_float).get<json::number_integer_t>());
852            CHECK_NOTHROW(
853                json(json::value_t::number_float).get<json::number_unsigned_t>());
854        }
855    }
856
857#if JSON_USE_IMPLICIT_CONVERSIONS
858    SECTION("get an integer number (implicit)")
859    {
860        json::number_integer_t n_reference{42};
861        json j(n_reference);
862        json::number_unsigned_t n_unsigned_reference{42u};
863        json j_unsigned(n_unsigned_reference);
864
865        SECTION("number_integer_t")
866        {
867            auto n = j.get<json::number_integer_t>();
868            CHECK(json(n) == j);
869        }
870
871        SECTION("number_unsigned_t")
872        {
873            auto n = j_unsigned.get<json::number_unsigned_t>();
874            CHECK(json(n) == j_unsigned);
875        }
876
877        SECTION("short")
878        {
879            short n = j;
880            CHECK(json(n) == j);
881        }
882
883        SECTION("unsigned short")
884        {
885            unsigned short n = j_unsigned;
886            CHECK(json(n) == j_unsigned);
887        }
888
889        SECTION("int")
890        {
891            int n = j;
892            CHECK(json(n) == j);
893        }
894
895        SECTION("unsigned int")
896        {
897            unsigned int n = j_unsigned;
898            CHECK(json(n) == j_unsigned);
899        }
900
901        SECTION("long")
902        {
903            long n = j;
904            CHECK(json(n) == j);
905        }
906
907        SECTION("unsigned long")
908        {
909            unsigned long n = j_unsigned;
910            CHECK(json(n) == j_unsigned);
911        }
912
913        SECTION("long long")
914        {
915            long long n = j;
916            CHECK(json(n) == j);
917        }
918
919        SECTION("unsigned long long")
920        {
921            unsigned long long n = j_unsigned;
922            CHECK(json(n) == j_unsigned);
923        }
924
925        SECTION("int8_t")
926        {
927            int8_t n = j;
928            CHECK(json(n) == j);
929        }
930
931        SECTION("int16_t")
932        {
933            int16_t n = j;
934            CHECK(json(n) == j);
935        }
936
937        SECTION("int32_t")
938        {
939            int32_t n = j;
940            CHECK(json(n) == j);
941        }
942
943        SECTION("int64_t")
944        {
945            int64_t n = j;
946            CHECK(json(n) == j);
947        }
948
949        SECTION("int8_fast_t")
950        {
951            int_fast8_t n = j;
952            CHECK(json(n) == j);
953        }
954
955        SECTION("int16_fast_t")
956        {
957            int_fast16_t n = j;
958            CHECK(json(n) == j);
959        }
960
961        SECTION("int32_fast_t")
962        {
963            int_fast32_t n = j;
964            CHECK(json(n) == j);
965        }
966
967        SECTION("int64_fast_t")
968        {
969            int_fast64_t n = j;
970            CHECK(json(n) == j);
971        }
972
973        SECTION("int8_least_t")
974        {
975            int_least8_t n = j;
976            CHECK(json(n) == j);
977        }
978
979        SECTION("int16_least_t")
980        {
981            int_least16_t n = j;
982            CHECK(json(n) == j);
983        }
984
985        SECTION("int32_least_t")
986        {
987            int_least32_t n = j;
988            CHECK(json(n) == j);
989        }
990
991        SECTION("int64_least_t")
992        {
993            int_least64_t n = j;
994            CHECK(json(n) == j);
995        }
996
997        SECTION("uint8_t")
998        {
999            uint8_t n = j_unsigned;
1000            CHECK(json(n) == j_unsigned);
1001        }
1002
1003        SECTION("uint16_t")
1004        {
1005            uint16_t n = j_unsigned;
1006            CHECK(json(n) == j_unsigned);
1007        }
1008
1009        SECTION("uint32_t")
1010        {
1011            uint32_t n = j_unsigned;
1012            CHECK(json(n) == j_unsigned);
1013        }
1014
1015        SECTION("uint64_t")
1016        {
1017            uint64_t n = j_unsigned;
1018            CHECK(json(n) == j_unsigned);
1019        }
1020
1021        SECTION("uint8_fast_t")
1022        {
1023            uint_fast8_t n = j_unsigned;
1024            CHECK(json(n) == j_unsigned);
1025        }
1026
1027        SECTION("uint16_fast_t")
1028        {
1029            uint_fast16_t n = j_unsigned;
1030            CHECK(json(n) == j_unsigned);
1031        }
1032
1033        SECTION("uint32_fast_t")
1034        {
1035            uint_fast32_t n = j_unsigned;
1036            CHECK(json(n) == j_unsigned);
1037        }
1038
1039        SECTION("uint64_fast_t")
1040        {
1041            uint_fast64_t n = j_unsigned;
1042            CHECK(json(n) == j_unsigned);
1043        }
1044
1045        SECTION("uint8_least_t")
1046        {
1047            uint_least8_t n = j_unsigned;
1048            CHECK(json(n) == j_unsigned);
1049        }
1050
1051        SECTION("uint16_least_t")
1052        {
1053            uint_least16_t n = j_unsigned;
1054            CHECK(json(n) == j_unsigned);
1055        }
1056
1057        SECTION("uint32_least_t")
1058        {
1059            uint_least32_t n = j_unsigned;
1060            CHECK(json(n) == j_unsigned);
1061        }
1062
1063        SECTION("uint64_least_t")
1064        {
1065            uint_least64_t n = j_unsigned;
1066            CHECK(json(n) == j_unsigned);
1067        }
1068    }
1069#endif
1070
1071    SECTION("get a floating-point number (explicit)")
1072    {
1073        json::number_float_t n_reference{42.23};
1074        json j(n_reference);
1075
1076        SECTION("number_float_t")
1077        {
1078            auto n = j.get<json::number_float_t>();
1079            CHECK(json(n).m_value.number_float == Approx(j.m_value.number_float));
1080        }
1081
1082        SECTION("float")
1083        {
1084            auto n = j.get<float>();
1085            CHECK(json(n).m_value.number_float == Approx(j.m_value.number_float));
1086        }
1087
1088        SECTION("double")
1089        {
1090            auto n = j.get<double>();
1091            CHECK(json(n).m_value.number_float == Approx(j.m_value.number_float));
1092        }
1093
1094        SECTION("exception in case of a non-string type")
1095        {
1096            CHECK_THROWS_WITH_AS(
1097                json(json::value_t::null).get<json::number_float_t>(),
1098                "[json.exception.type_error.302] type must be number, but is null", json::type_error&);
1099            CHECK_THROWS_WITH_AS(
1100                json(json::value_t::object).get<json::number_float_t>(),
1101                "[json.exception.type_error.302] type must be number, but is object", json::type_error&);
1102            CHECK_THROWS_WITH_AS(
1103                json(json::value_t::array).get<json::number_float_t>(),
1104                "[json.exception.type_error.302] type must be number, but is array", json::type_error&);
1105            CHECK_THROWS_WITH_AS(
1106                json(json::value_t::string).get<json::number_float_t>(),
1107                "[json.exception.type_error.302] type must be number, but is string", json::type_error&);
1108            CHECK_THROWS_WITH_AS(
1109                json(json::value_t::boolean).get<json::number_float_t>(),
1110                "[json.exception.type_error.302] type must be number, but is "
1111                "boolean", json::type_error&);
1112
1113            CHECK_NOTHROW(
1114                json(json::value_t::number_integer).get<json::number_float_t>());
1115            CHECK_NOTHROW(
1116                json(json::value_t::number_unsigned).get<json::number_float_t>());
1117        }
1118    }
1119
1120#if JSON_USE_IMPLICIT_CONVERSIONS
1121    SECTION("get a floating-point number (implicit)")
1122    {
1123        json::number_float_t n_reference{42.23};
1124        json j(n_reference);
1125
1126        SECTION("number_float_t")
1127        {
1128            json::number_float_t n = j;
1129            CHECK(json(n).m_value.number_float == Approx(j.m_value.number_float));
1130        }
1131
1132        SECTION("float")
1133        {
1134            float n = j;
1135            CHECK(json(n).m_value.number_float == Approx(j.m_value.number_float));
1136        }
1137
1138        SECTION("double")
1139        {
1140            double n = j;
1141            CHECK(json(n).m_value.number_float == Approx(j.m_value.number_float));
1142        }
1143    }
1144#endif
1145
1146    SECTION("get a binary value (explicit)")
1147    {
1148        json::binary_t n_reference{{1, 2, 3}};
1149        json j(n_reference);
1150
1151        SECTION("binary_t")
1152        {
1153            json::binary_t b = j.get<json::binary_t>();
1154            CHECK(*json(b).m_value.binary == *j.m_value.binary);
1155        }
1156
1157        SECTION("get_binary()")
1158        {
1159            SECTION("non-const")
1160            {
1161                auto& b = j.get_binary();
1162                CHECK(*json(b).m_value.binary == *j.m_value.binary);
1163            }
1164
1165            SECTION("non-const")
1166            {
1167                const json j_const = j;
1168                const auto& b = j_const.get_binary();
1169                CHECK(*json(b).m_value.binary == *j.m_value.binary);
1170            }
1171        }
1172
1173        SECTION("exception in case of a non-string type")
1174        {
1175            json j_null(json::value_t::null);
1176            json j_object(json::value_t::object);
1177            json j_array(json::value_t::array);
1178            json j_string(json::value_t::string);
1179            json j_boolean(json::value_t::boolean);
1180            const json j_null_const(json::value_t::null);
1181            const json j_object_const(json::value_t::object);
1182            const json j_array_const(json::value_t::array);
1183            const json j_string_const(json::value_t::string);
1184            const json j_boolean_const(json::value_t::boolean);
1185
1186            CHECK_THROWS_WITH_AS(j_null.get<json::binary_t>(),
1187                                 "[json.exception.type_error.302] type must be binary, but is null",
1188                                 json::type_error&);
1189            CHECK_THROWS_WITH_AS(j_object.get<json::binary_t>(),
1190                                 "[json.exception.type_error.302] type must be binary, but is object",
1191                                 json::type_error&);
1192            CHECK_THROWS_WITH_AS(j_array.get<json::binary_t>(),
1193                                 "[json.exception.type_error.302] type must be binary, but is array",
1194                                 json::type_error&);
1195            CHECK_THROWS_WITH_AS(j_string.get<json::binary_t>(),
1196                                 "[json.exception.type_error.302] type must be binary, but is string",
1197                                 json::type_error&);
1198            CHECK_THROWS_WITH_AS(j_boolean.get<json::binary_t>(),
1199                                 "[json.exception.type_error.302] type must be binary, but is boolean",
1200                                 json::type_error&);
1201
1202            CHECK_THROWS_WITH_AS(j_null_const.get<json::binary_t>(),
1203                                 "[json.exception.type_error.302] type must be binary, but is null",
1204                                 json::type_error&);
1205            CHECK_THROWS_WITH_AS(j_object_const.get<json::binary_t>(),
1206                                 "[json.exception.type_error.302] type must be binary, but is object",
1207                                 json::type_error&);
1208            CHECK_THROWS_WITH_AS(j_array_const.get<json::binary_t>(),
1209                                 "[json.exception.type_error.302] type must be binary, but is array",
1210                                 json::type_error&);
1211            CHECK_THROWS_WITH_AS(j_string_const.get<json::binary_t>(),
1212                                 "[json.exception.type_error.302] type must be binary, but is string",
1213                                 json::type_error&);
1214            CHECK_THROWS_WITH_AS(j_boolean_const.get<json::binary_t>(),
1215                                 "[json.exception.type_error.302] type must be binary, but is boolean",
1216                                 json::type_error&);
1217
1218            CHECK_THROWS_WITH_AS(j_null.get_binary(),
1219                                 "[json.exception.type_error.302] type must be binary, but is null",
1220                                 json::type_error&);
1221            CHECK_THROWS_WITH_AS(j_object.get_binary(),
1222                                 "[json.exception.type_error.302] type must be binary, but is object",
1223                                 json::type_error&);
1224            CHECK_THROWS_WITH_AS(j_array.get_binary(),
1225                                 "[json.exception.type_error.302] type must be binary, but is array",
1226                                 json::type_error&);
1227            CHECK_THROWS_WITH_AS(j_string.get_binary(),
1228                                 "[json.exception.type_error.302] type must be binary, but is string",
1229                                 json::type_error&);
1230            CHECK_THROWS_WITH_AS(j_boolean.get_binary(),
1231                                 "[json.exception.type_error.302] type must be binary, but is boolean",
1232                                 json::type_error&);
1233
1234            CHECK_THROWS_WITH_AS(j_null_const.get_binary(),
1235                                 "[json.exception.type_error.302] type must be binary, but is null",
1236                                 json::type_error&);
1237            CHECK_THROWS_WITH_AS(j_object_const.get_binary(),
1238                                 "[json.exception.type_error.302] type must be binary, but is object",
1239                                 json::type_error&);
1240            CHECK_THROWS_WITH_AS(j_array_const.get_binary(),
1241                                 "[json.exception.type_error.302] type must be binary, but is array",
1242                                 json::type_error&);
1243            CHECK_THROWS_WITH_AS(j_string_const.get_binary(),
1244                                 "[json.exception.type_error.302] type must be binary, but is string",
1245                                 json::type_error&);
1246            CHECK_THROWS_WITH_AS(j_boolean_const.get_binary(),
1247                                 "[json.exception.type_error.302] type must be binary, but is boolean",
1248                                 json::type_error&);
1249        }
1250    }
1251
1252#if JSON_USE_IMPLICIT_CONVERSIONS
1253    SECTION("get a binary value (implicit)")
1254    {
1255        json::binary_t n_reference{{1, 2, 3}};
1256        json j(n_reference);
1257
1258        SECTION("binary_t")
1259        {
1260            json::binary_t b = j;
1261            CHECK(*json(b).m_value.binary == *j.m_value.binary);
1262        }
1263    }
1264#endif
1265
1266    SECTION("get an enum")
1267    {
1268        enum c_enum { value_1, value_2 };
1269        enum class cpp_enum { value_1, value_2 };
1270
1271        CHECK(json(value_1).get<c_enum>() == value_1);
1272        CHECK(json(cpp_enum::value_1).get<cpp_enum>() == cpp_enum::value_1);
1273    }
1274
1275    SECTION("more involved conversions")
1276    {
1277        SECTION("object-like STL containers")
1278        {
1279            json j1 = {{"one", 1}, {"two", 2}, {"three", 3}};
1280            json j2 = {{"one", 1u}, {"two", 2u}, {"three", 3u}};
1281            json j3 = {{"one", 1.1}, {"two", 2.2}, {"three", 3.3}};
1282            json j4 = {{"one", true}, {"two", false}, {"three", true}};
1283            json j5 = {{"one", "eins"}, {"two", "zwei"}, {"three", "drei"}};
1284
1285            SECTION("std::map")
1286            {
1287                j1.get<std::map<std::string, int>>();
1288                j2.get<std::map<std::string, unsigned int>>();
1289                j3.get<std::map<std::string, double>>();
1290                j4.get<std::map<std::string, bool>>();
1291                j5.get<std::map<std::string, std::string>>();
1292            }
1293
1294            SECTION("std::unordered_map")
1295            {
1296                j1.get<std::unordered_map<std::string, int>>();
1297                j2.get<std::unordered_map<std::string, unsigned int>>();
1298                j3.get<std::unordered_map<std::string, double>>();
1299                j4.get<std::unordered_map<std::string, bool>>();
1300                j5.get<std::unordered_map<std::string, std::string>>();
1301                // CHECK(m5["one"] == "eins");
1302            }
1303
1304            SECTION("std::multimap")
1305            {
1306                j1.get<std::multimap<std::string, int>>();
1307                j2.get<std::multimap<std::string, unsigned int>>();
1308                j3.get<std::multimap<std::string, double>>();
1309                j4.get<std::multimap<std::string, bool>>();
1310                j5.get<std::multimap<std::string, std::string>>();
1311                // CHECK(m5["one"] == "eins");
1312            }
1313
1314            SECTION("std::unordered_multimap")
1315            {
1316                j1.get<std::unordered_multimap<std::string, int>>();
1317                j2.get<std::unordered_multimap<std::string, unsigned int>>();
1318                j3.get<std::unordered_multimap<std::string, double>>();
1319                j4.get<std::unordered_multimap<std::string, bool>>();
1320                j5.get<std::unordered_multimap<std::string, std::string>>();
1321                // CHECK(m5["one"] == "eins");
1322            }
1323
1324            SECTION("exception in case of a non-object type")
1325            {
1326                CHECK_THROWS_WITH_AS(
1327                    (json().get<std::map<std::string, int>>()),
1328                    "[json.exception.type_error.302] type must be object, but is null", json::type_error&);
1329            }
1330        }
1331
1332        SECTION("array-like STL containers")
1333        {
1334            json j1 = {1, 2, 3, 4};
1335            json j2 = {1u, 2u, 3u, 4u};
1336            json j3 = {1.2, 2.3, 3.4, 4.5};
1337            json j4 = {true, false, true};
1338            json j5 = {"one", "two", "three"};
1339
1340            SECTION("std::list")
1341            {
1342                j1.get<std::list<int>>();
1343                j2.get<std::list<unsigned int>>();
1344                j3.get<std::list<double>>();
1345                j4.get<std::list<bool>>();
1346                j5.get<std::list<std::string>>();
1347            }
1348
1349            SECTION("std::forward_list")
1350            {
1351                j1.get<std::forward_list<int>>();
1352                j2.get<std::forward_list<unsigned int>>();
1353                j3.get<std::forward_list<double>>();
1354                j4.get<std::forward_list<bool>>();
1355                j5.get<std::forward_list<std::string>>();
1356            }
1357
1358            SECTION("std::array")
1359            {
1360                j1.get<std::array<int, 4>>();
1361                j2.get<std::array<unsigned int, 3>>();
1362                j3.get<std::array<double, 4>>();
1363                j4.get<std::array<bool, 3>>();
1364                j5.get<std::array<std::string, 3>>();
1365
1366                SECTION("std::array is larger than JSON")
1367                {
1368                    std::array<int, 6> arr6 = {{1, 2, 3, 4, 5, 6}};
1369                    CHECK_THROWS_WITH_AS(j1.get_to(arr6), "[json.exception.out_of_range.401] "
1370                                         "array index 4 is out of range", json::out_of_range&);
1371                }
1372
1373                SECTION("std::array is smaller than JSON")
1374                {
1375                    std::array<int, 2> arr2 = {{8, 9}};
1376                    j1.get_to(arr2);
1377                    CHECK(arr2[0] == 1);
1378                    CHECK(arr2[1] == 2);
1379                }
1380            }
1381
1382            SECTION("std::valarray")
1383            {
1384                j1.get<std::valarray<int>>();
1385                j2.get<std::valarray<unsigned int>>();
1386                j3.get<std::valarray<double>>();
1387                j4.get<std::valarray<bool>>();
1388                j5.get<std::valarray<std::string>>();
1389            }
1390
1391            SECTION("std::vector")
1392            {
1393                j1.get<std::vector<int>>();
1394                j2.get<std::vector<unsigned int>>();
1395                j3.get<std::vector<double>>();
1396                j4.get<std::vector<bool>>();
1397                j5.get<std::vector<std::string>>();
1398            }
1399
1400            SECTION("std::deque")
1401            {
1402                j1.get<std::deque<int>>();
1403                j2.get<std::deque<unsigned int>>();
1404                j2.get<std::deque<double>>();
1405                j4.get<std::deque<bool>>();
1406                j5.get<std::deque<std::string>>();
1407            }
1408
1409            SECTION("std::set")
1410            {
1411                j1.get<std::set<int>>();
1412                j2.get<std::set<unsigned int>>();
1413                j3.get<std::set<double>>();
1414                j4.get<std::set<bool>>();
1415                j5.get<std::set<std::string>>();
1416            }
1417
1418            SECTION("std::unordered_set")
1419            {
1420                j1.get<std::unordered_set<int>>();
1421                j2.get<std::unordered_set<unsigned int>>();
1422                j3.get<std::unordered_set<double>>();
1423                j4.get<std::unordered_set<bool>>();
1424                j5.get<std::unordered_set<std::string>>();
1425            }
1426
1427            SECTION("std::map (array of pairs)")
1428            {
1429                std::map<int, int> m{{0, 1}, {1, 2}, {2, 3}};
1430                json j6 = m;
1431
1432                auto m2 = j6.get<std::map<int, int>>();
1433                CHECK(m == m2);
1434
1435                json j7 = {0, 1, 2, 3};
1436                json j8 = 2;
1437                CHECK_THROWS_WITH_AS((j7.get<std::map<int, int>>()),
1438                                     "[json.exception.type_error.302] type must be array, "
1439                                     "but is number", json::type_error&);
1440                CHECK_THROWS_WITH_AS((j8.get<std::map<int, int>>()),
1441                                     "[json.exception.type_error.302] type must be array, "
1442                                     "but is number", json::type_error&);
1443
1444                SECTION("superfluous entries")
1445                {
1446                    json j9 = {{0, 1, 2}, {1, 2, 3}, {2, 3, 4}};
1447                    m2 = j9.get<std::map<int, int>>();
1448                    CHECK(m == m2);
1449                }
1450            }
1451
1452            SECTION("std::unordered_map (array of pairs)")
1453            {
1454                std::unordered_map<int, int> m{{0, 1}, {1, 2}, {2, 3}};
1455                json j6 = m;
1456
1457                auto m2 = j6.get<std::unordered_map<int, int>>();
1458                CHECK(m == m2);
1459
1460                json j7 = {0, 1, 2, 3};
1461                json j8 = 2;
1462                CHECK_THROWS_WITH_AS((j7.get<std::unordered_map<int, int>>()),
1463                                     "[json.exception.type_error.302] type must be array, "
1464                                     "but is number", json::type_error&);
1465                CHECK_THROWS_WITH_AS((j8.get<std::unordered_map<int, int>>()),
1466                                     "[json.exception.type_error.302] type must be array, "
1467                                     "but is number", json::type_error&);
1468
1469                SECTION("superfluous entries")
1470                {
1471                    json j9{{0, 1, 2}, {1, 2, 3}, {2, 3, 4}};
1472                    m2 = j9.get<std::unordered_map<int, int>>();
1473                    CHECK(m == m2);
1474                }
1475            }
1476
1477            SECTION("exception in case of a non-object type")
1478            {
1479                // does type really must be an array? or it rather must not be null?
1480                // that's what I thought when other test like this one broke
1481                CHECK_THROWS_WITH_AS(
1482                    (json().get<std::list<int>>()),
1483                    "[json.exception.type_error.302] type must be array, but is null", json::type_error&);
1484                CHECK_THROWS_WITH_AS(
1485                    (json().get<std::vector<int>>()),
1486                    "[json.exception.type_error.302] type must be array, but is null", json::type_error&);
1487                CHECK_THROWS_WITH_AS(
1488                    (json().get<std::vector<json>>()),
1489                    "[json.exception.type_error.302] type must be array, but is null", json::type_error&);
1490                CHECK_THROWS_WITH_AS(
1491                    (json().get<std::list<json>>()),
1492                    "[json.exception.type_error.302] type must be array, but is null", json::type_error&);
1493                CHECK_THROWS_WITH_AS(
1494                    (json().get<std::valarray<int>>()),
1495                    "[json.exception.type_error.302] type must be array, but is null", json::type_error&);
1496                CHECK_THROWS_WITH_AS(
1497                    (json().get<std::map<int, int>>()),
1498                    "[json.exception.type_error.302] type must be array, but is null", json::type_error&);
1499            }
1500        }
1501    }
1502}
1503
1504enum class cards {kreuz, pik, herz, karo};
1505
1506// NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) - false positive
1507NLOHMANN_JSON_SERIALIZE_ENUM(cards,
1508{
1509    {cards::kreuz, "kreuz"},
1510    {cards::pik, "pik"},
1511    {cards::pik, "puk"},  // second entry for cards::puk; will not be used
1512    {cards::herz, "herz"},
1513    {cards::karo, "karo"}
1514})
1515
1516enum TaskState
1517{
1518    TS_STOPPED,
1519    TS_RUNNING,
1520    TS_COMPLETED,
1521    TS_INVALID = -1,
1522};
1523
1524// NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) - false positive
1525NLOHMANN_JSON_SERIALIZE_ENUM(TaskState,
1526{
1527    {TS_INVALID, nullptr},
1528    {TS_STOPPED, "stopped"},
1529    {TS_RUNNING, "running"},
1530    {TS_COMPLETED, "completed"},
1531})
1532
1533TEST_CASE("JSON to enum mapping")
1534{
1535    SECTION("enum class")
1536    {
1537        // enum -> json
1538        CHECK(json(cards::kreuz) == "kreuz");
1539        CHECK(json(cards::pik) == "pik");
1540        CHECK(json(cards::herz) == "herz");
1541        CHECK(json(cards::karo) == "karo");
1542
1543        // json -> enum
1544        CHECK(cards::kreuz == json("kreuz"));
1545        CHECK(cards::pik == json("pik"));
1546        CHECK(cards::herz == json("herz"));
1547        CHECK(cards::karo == json("karo"));
1548
1549        // invalid json -> first enum
1550        CHECK(cards::kreuz == json("what?").get<cards>());
1551    }
1552
1553    SECTION("traditional enum")
1554    {
1555        // enum -> json
1556        CHECK(json(TS_STOPPED) == "stopped");
1557        CHECK(json(TS_RUNNING) == "running");
1558        CHECK(json(TS_COMPLETED) == "completed");
1559        CHECK(json(TS_INVALID) == json());
1560
1561        // json -> enum
1562        CHECK(TS_STOPPED == json("stopped"));
1563        CHECK(TS_RUNNING == json("running"));
1564        CHECK(TS_COMPLETED == json("completed"));
1565        CHECK(TS_INVALID == json());
1566
1567        // invalid json -> first enum
1568        CHECK(TS_INVALID == json("what?").get<TaskState>());
1569    }
1570}
1571
1572DOCTEST_CLANG_SUPPRESS_WARNING_POP
1573