• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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>
21 using 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
32 DOCTEST_CLANG_SUPPRESS_WARNING_PUSH
33 DOCTEST_CLANG_SUPPRESS_WARNING("-Wexit-time-destructors")
34 
35 TEST_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 
1504 enum class cards {kreuz, pik, herz, karo};
1505 
1506 // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) - false positive
1507 NLOHMANN_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 
1516 enum 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
1525 NLOHMANN_JSON_SERIALIZE_ENUM(TaskState,
1526 {
1527     {TS_INVALID, nullptr},
1528     {TS_STOPPED, "stopped"},
1529     {TS_RUNNING, "running"},
1530     {TS_COMPLETED, "completed"},
1531 })
1532 
1533 TEST_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 
1572 DOCTEST_CLANG_SUPPRESS_WARNING_POP
1573