summaryrefslogtreecommitdiff
path: root/json4cpp/tests/src/unit-conversions.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'json4cpp/tests/src/unit-conversions.cpp')
-rw-r--r--json4cpp/tests/src/unit-conversions.cpp1753
1 files changed, 1753 insertions, 0 deletions
diff --git a/json4cpp/tests/src/unit-conversions.cpp b/json4cpp/tests/src/unit-conversions.cpp
new file mode 100644
index 0000000000..81b8608fb8
--- /dev/null
+++ b/json4cpp/tests/src/unit-conversions.cpp
@@ -0,0 +1,1753 @@
+// __ _____ _____ _____
+// __| | __| | | | JSON for Modern C++ (supporting code)
+// | | |__ | | | | | | version 3.12.0
+// |_____|_____|_____|_|___| https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+// cmake/test.cmake selects the C++ standard versions with which to build a
+// unit test based on the presence of JSON_HAS_CPP_<VERSION> macros.
+// When using macros that are only defined for particular versions of the standard
+// (e.g., JSON_HAS_FILESYSTEM for C++17 and up), please mention the corresponding
+// version macro in a comment close by, like this:
+// JSON_HAS_CPP_<VERSION> (do not remove; see note at top of file)
+
+#include "doctest_compatibility.h"
+
+// skip tests if JSON_DisableEnumSerialization=ON (#4384)
+#if defined(JSON_DISABLE_ENUM_SERIALIZATION) && (JSON_DISABLE_ENUM_SERIALIZATION == 1)
+ #define SKIP_TESTS_FOR_ENUM_SERIALIZATION
+#endif
+
+#define JSON_TESTS_PRIVATE
+#include <nlohmann/json.hpp>
+using nlohmann::json;
+
+#include <deque>
+#include <forward_list>
+#include <list>
+#include <set>
+#include <unordered_map>
+#include <unordered_set>
+#include <valarray>
+
+// NLOHMANN_JSON_SERIALIZE_ENUM uses a static std::pair
+DOCTEST_CLANG_SUPPRESS_WARNING_PUSH
+DOCTEST_CLANG_SUPPRESS_WARNING("-Wexit-time-destructors")
+
+#if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
+ #define JSON_HAS_CPP_17
+ #define JSON_HAS_CPP_14
+#elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
+ #define JSON_HAS_CPP_14
+#endif
+
+#ifdef JSON_HAS_CPP_17
+ #if __has_include(<optional>)
+ #include <optional>
+ #elif __has_include(<experimental/optional>)
+ #include <experimental/optional>
+ #endif
+#endif
+
+#if defined(JSON_HAS_CPP_17)
+ #include <string_view>
+#endif
+
+TEST_CASE("value conversion")
+{
+ SECTION("get an object (explicit)")
+ {
+ const json::object_t o_reference = {{"object", json::object()},
+ {"array", {1, 2, 3, 4}},
+ {"number", 42},
+ {"boolean", false},
+ {"null", nullptr},
+ {"string", "Hello world"}
+ };
+ json j(o_reference);
+
+ SECTION("json::object_t")
+ {
+ json::object_t const o = j.get<json::object_t>();
+ CHECK(json(o) == j);
+ }
+
+ SECTION("std::map<json::string_t, json>")
+ {
+ const std::map<json::string_t, json> o =
+ j.get<std::map<json::string_t, json>>();
+ CHECK(json(o) == j);
+ }
+
+ SECTION("std::multimap<json::string_t, json>")
+ {
+ const std::multimap<json::string_t, json> o =
+ j.get<std::multimap<json::string_t, json>>();
+ CHECK(json(o) == j);
+ }
+
+ SECTION("std::unordered_map<json::string_t, json>")
+ {
+ const std::unordered_map<json::string_t, json> o =
+ j.get<std::unordered_map<json::string_t, json>>();
+ CHECK(json(o) == j);
+ }
+
+ SECTION("std::unordered_multimap<json::string_t, json>")
+ {
+ const std::unordered_multimap<json::string_t, json> o =
+ j.get<std::unordered_multimap<json::string_t, json>>();
+ CHECK(json(o) == j);
+ }
+
+ SECTION("exception in case of a non-object type")
+ {
+ CHECK_THROWS_WITH_AS(
+ json(json::value_t::null).get<json::object_t>(),
+ "[json.exception.type_error.302] type must be object, but is null", json::type_error&);
+ CHECK_THROWS_WITH_AS(
+ json(json::value_t::array).get<json::object_t>(),
+ "[json.exception.type_error.302] type must be object, but is array", json::type_error&);
+ CHECK_THROWS_WITH_AS(
+ json(json::value_t::string).get<json::object_t>(),
+ "[json.exception.type_error.302] type must be object, but is string", json::type_error&);
+ CHECK_THROWS_WITH_AS(json(json::value_t::boolean).get<json::object_t>(),
+ "[json.exception.type_error.302] type must be object, "
+ "but is boolean", json::type_error&);
+ CHECK_THROWS_WITH_AS(
+ json(json::value_t::number_integer).get<json::object_t>(),
+ "[json.exception.type_error.302] type must be object, but is number", json::type_error&);
+ CHECK_THROWS_WITH_AS(
+ json(json::value_t::number_unsigned).get<json::object_t>(),
+ "[json.exception.type_error.302] type must be object, but is number", json::type_error&);
+ CHECK_THROWS_WITH_AS(
+ json(json::value_t::number_float).get<json::object_t>(),
+ "[json.exception.type_error.302] type must be object, but is number", json::type_error&);
+ }
+ }
+
+ SECTION("get an object (explicit, get_to)")
+ {
+ const json::object_t o_reference = {{"object", json::object()},
+ {"array", {1, 2, 3, 4}},
+ {"number", 42},
+ {"boolean", false},
+ {"null", nullptr},
+ {"string", "Hello world"}
+ };
+ json j(o_reference);
+
+ SECTION("json::object_t")
+ {
+ json::object_t o = {{"previous", "value"}};
+ j.get_to(o);
+ CHECK(json(o) == j);
+ }
+
+ SECTION("std::map<json::string_t, json>")
+ {
+ std::map<json::string_t, json> o{{"previous", "value"}};
+ j.get_to(o);
+ CHECK(json(o) == j);
+ }
+
+ SECTION("std::multimap<json::string_t, json>")
+ {
+ std::multimap<json::string_t, json> o{{"previous", "value"}};
+ j.get_to(o);
+ CHECK(json(o) == j);
+ }
+
+ SECTION("std::unordered_map<json::string_t, json>")
+ {
+ std::unordered_map<json::string_t, json> o{{"previous", "value"}};
+ j.get_to(o);
+ CHECK(json(o) == j);
+ }
+
+ SECTION("std::unordered_multimap<json::string_t, json>")
+ {
+ std::unordered_multimap<json::string_t, json> o{{"previous", "value"}};
+ j.get_to(o);
+ CHECK(json(o) == j);
+ }
+ }
+
+#if JSON_USE_IMPLICIT_CONVERSIONS
+
+ SECTION("get an object (implicit)")
+ {
+ const json::object_t o_reference = {{"object", json::object()},
+ {"array", {1, 2, 3, 4}},
+ {"number", 42},
+ {"boolean", false},
+ {"null", nullptr},
+ {"string", "Hello world"}
+ };
+ json j(o_reference);
+
+ SECTION("json::object_t")
+ {
+ const json::object_t o = j;
+ CHECK(json(o) == j);
+ }
+
+ SECTION("std::map<json::string_t, json>")
+ {
+ const std::map<json::string_t, json> o = j;
+ CHECK(json(o) == j);
+ }
+
+ SECTION("std::multimap<json::string_t, json>")
+ {
+ const std::multimap<json::string_t, json> o = j;
+ CHECK(json(o) == j);
+ }
+
+ SECTION("std::unordered_map<json::string_t, json>")
+ {
+ const std::unordered_map<json::string_t, json> o = j;
+ CHECK(json(o) == j);
+ }
+
+ SECTION("std::unordered_multimap<json::string_t, json>")
+ {
+ const std::unordered_multimap<json::string_t, json> o = j;
+ CHECK(json(o) == j);
+ }
+ }
+#endif
+
+ SECTION("get an array (explicit)")
+ {
+ const json::array_t a_reference{json(1), json(1u), json(2.2),
+ json(false), json("string"), json()};
+ json j(a_reference);
+
+ SECTION("json::array_t")
+ {
+ const json::array_t a = j.get<json::array_t>();
+ CHECK(json(a) == j);
+ }
+
+ SECTION("std::list<json>")
+ {
+ const std::list<json> a = j.get<std::list<json>>();
+ CHECK(json(a) == j);
+ }
+
+ SECTION("std::forward_list<json>")
+ {
+ const std::forward_list<json> a = j.get<std::forward_list<json>>();
+ CHECK(json(a) == j);
+
+ CHECK_THROWS_WITH_AS(
+ json(json::value_t::null).get<std::forward_list<json>>(),
+ "[json.exception.type_error.302] type must be array, but is null", json::type_error&);
+ }
+
+ SECTION("std::vector<json>")
+ {
+ const std::vector<json> a = j.get<std::vector<json>>();
+ CHECK(json(a) == j);
+
+ CHECK_THROWS_WITH_AS(
+ json(json::value_t::null).get<std::vector<json>>(),
+ "[json.exception.type_error.302] type must be array, but is null", json::type_error&);
+
+#if !defined(JSON_NOEXCEPTION)
+ SECTION("reserve is called on containers that supports it")
+ {
+ // make sure all values are properly copied
+ const json j2({1, 2, 3, 4, 5, 6, 7, 8, 9, 10});
+ auto v2 = j2.get<std::vector<int>>();
+ CHECK(v2.size() == 10);
+ }
+#endif
+ }
+
+ SECTION("built-in arrays")
+ {
+ const char str[] = "a string"; // NOLINT(misc-const-correctness,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
+ const int nbs[] = {0, 1, 2}; // NOLINT(misc-const-correctness,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
+
+ const json j2 = nbs;
+ const json j3 = str;
+
+ auto v = j2.get<std::vector<int>>();
+ auto s = j3.get<std::string>();
+ CHECK(std::equal(v.begin(), v.end(), std::begin(nbs)));
+ CHECK(s == str);
+ }
+
+ SECTION("std::deque<json>")
+ {
+ const std::deque<json> a = j.get<std::deque<json>>();
+ CHECK(json(a) == j);
+ }
+
+ SECTION("exception in case of a non-array type")
+ {
+ CHECK_THROWS_WITH_AS(
+ json(json::value_t::object).get<std::vector<int>>(),
+ "[json.exception.type_error.302] type must be array, but is object", json::type_error&);
+ CHECK_THROWS_WITH_AS(
+ json(json::value_t::null).get<json::array_t>(),
+ "[json.exception.type_error.302] type must be array, but is null", json::type_error&);
+ CHECK_THROWS_WITH_AS(
+ json(json::value_t::object).get<json::array_t>(),
+ "[json.exception.type_error.302] type must be array, but is object", json::type_error&);
+ CHECK_THROWS_WITH_AS(
+ json(json::value_t::string).get<json::array_t>(),
+ "[json.exception.type_error.302] type must be array, but is string", json::type_error&);
+ CHECK_THROWS_WITH_AS(
+ json(json::value_t::boolean).get<json::array_t>(),
+ "[json.exception.type_error.302] type must be array, but is boolean", json::type_error&);
+ CHECK_THROWS_WITH_AS(
+ json(json::value_t::number_integer).get<json::array_t>(),
+ "[json.exception.type_error.302] type must be array, but is number", json::type_error&);
+ CHECK_THROWS_WITH_AS(
+ json(json::value_t::number_unsigned).get<json::array_t>(),
+ "[json.exception.type_error.302] type must be array, but is number", json::type_error&);
+ CHECK_THROWS_WITH_AS(
+ json(json::value_t::number_float).get<json::array_t>(),
+ "[json.exception.type_error.302] type must be array, but is number", json::type_error&);
+ }
+ }
+
+ SECTION("get an array (explicit, get_to)")
+ {
+ const json::array_t a_reference{json(1), json(1u), json(2.2),
+ json(false), json("string"), json()};
+ json j(a_reference);
+
+ SECTION("json::array_t")
+ {
+ json::array_t a{"previous", "value"};
+ j.get_to(a);
+ CHECK(json(a) == j);
+ }
+
+ SECTION("std::valarray<json>")
+ {
+ std::valarray<json> a{"previous", "value"};
+ j.get_to(a);
+ CHECK(json(a) == j);
+ }
+
+ SECTION("std::list<json>")
+ {
+ std::list<json> a{"previous", "value"};
+ j.get_to(a);
+ CHECK(json(a) == j);
+ }
+
+ SECTION("std::forward_list<json>")
+ {
+ std::forward_list<json> a{"previous", "value"};
+ j.get_to(a);
+ CHECK(json(a) == j);
+ }
+
+ SECTION("std::vector<json>")
+ {
+ std::vector<json> a{"previous", "value"};
+ j.get_to(a);
+ CHECK(json(a) == j);
+ }
+
+ SECTION("built-in arrays")
+ {
+ const int nbs[] = {0, 1, 2}; // NOLINT(misc-const-correctness,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
+ int nbs2[] = {0, 0, 0}; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
+
+ const json j2 = nbs;
+ j2.get_to(nbs2);
+ CHECK(std::equal(std::begin(nbs), std::end(nbs), std::begin(nbs2)));
+ }
+
+ SECTION("built-in arrays: 2D")
+ {
+ const int nbs[][3] = {{0, 1, 2}, {3, 4, 5}}; // NOLINT(misc-const-correctness,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
+ int nbs2[][3] = {{0, 0, 0}, {0, 0, 0}}; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
+
+ const json j2 = nbs;
+ j2.get_to(nbs2);
+ CHECK(std::equal(std::begin(nbs[0]), std::end(nbs[1]), std::begin(nbs2[0])));
+ }
+
+ SECTION("built-in arrays: 3D")
+ {
+ // NOLINTBEGIN(misc-const-correctness,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
+ const int nbs[][2][3] = {\
+ {{0, 1, 2}, {3, 4, 5}}, \
+ {{10, 11, 12}, {13, 14, 15}}\
+ };
+ int nbs2[][2][3] = {\
+ {{0, 0, 0}, {0, 0, 0}}, \
+ {{0, 0, 0}, {0, 0, 0}}\
+ };
+ // NOLINTEND(misc-const-correctness,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
+
+ const json j2 = nbs;
+ j2.get_to(nbs2);
+ CHECK(std::equal(std::begin(nbs[0][0]), std::end(nbs[1][1]), std::begin(nbs2[0][0])));
+ }
+
+ SECTION("built-in arrays: 4D")
+ {
+ // NOLINTBEGIN(misc-const-correctness,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
+ const int nbs[][2][2][3] = {\
+ {
+ \
+ {{0, 1, 2}, {3, 4, 5}}, \
+ {{10, 11, 12}, {13, 14, 15}}\
+ }, \
+ {
+ \
+ {{20, 21, 22}, {23, 24, 25}}, \
+ {{30, 31, 32}, {33, 34, 35}}\
+ }\
+ };
+ int nbs2[][2][2][3] = {\
+ {
+ \
+ {{0, 0, 0}, {0, 0, 0}}, \
+ {{0, 0, 0}, {0, 0, 0}}\
+ }, \
+ {
+ \
+ {{0, 0, 0}, {0, 0, 0}}, \
+ {{0, 0, 0}, {0, 0, 0}}\
+ }\
+ };
+ // NOLINTEND(misc-const-correctness,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
+
+ const json j2 = nbs;
+ j2.get_to(nbs2);
+ CHECK(std::equal(std::begin(nbs[0][0][0]), std::end(nbs[1][1][1]), std::begin(nbs2[0][0][0])));
+ }
+
+ SECTION("std::deque<json>")
+ {
+ std::deque<json> a{"previous", "value"};
+ j.get_to(a);
+ CHECK(json(a) == j);
+ }
+ }
+
+#if JSON_USE_IMPLICIT_CONVERSIONS
+ SECTION("get an array (implicit)")
+ {
+ const json::array_t a_reference{json(1), json(1u), json(2.2),
+ json(false), json("string"), json()};
+ json j(a_reference);
+
+ SECTION("json::array_t")
+ {
+ const json::array_t a = j;
+ CHECK(json(a) == j);
+ }
+
+ SECTION("std::list<json>")
+ {
+ const std::list<json> a = j;
+ CHECK(json(a) == j);
+ }
+
+ SECTION("std::forward_list<json>")
+ {
+ const std::forward_list<json> a = j;
+ CHECK(json(a) == j);
+ }
+
+ SECTION("std::vector<json>")
+ {
+ const std::vector<json> a = j;
+ CHECK(json(a) == j);
+ }
+
+ SECTION("std::deque<json>")
+ {
+ const std::deque<json> a = j;
+ CHECK(json(a) == j);
+ }
+ }
+#endif
+
+ SECTION("get a string (explicit)")
+ {
+ const json::string_t s_reference{"Hello world"};
+ json j(s_reference);
+
+ SECTION("string_t")
+ {
+ const json::string_t s = j.get<json::string_t>();
+ CHECK(json(s) == j);
+ }
+
+ SECTION("std::string")
+ {
+ const std::string s = j.get<std::string>();
+ CHECK(json(s) == j);
+ }
+#if defined(JSON_HAS_CPP_17)
+ SECTION("std::string_view")
+ {
+ std::string_view const s = j.get<std::string_view>();
+ CHECK(json(s) == j);
+ }
+#endif
+
+ SECTION("exception in case of a non-string type")
+ {
+ CHECK_THROWS_WITH_AS(
+ json(json::value_t::null).get<json::string_t>(),
+ "[json.exception.type_error.302] type must be string, but is null", json::type_error&);
+ CHECK_THROWS_WITH_AS(
+ json(json::value_t::object).get<json::string_t>(),
+ "[json.exception.type_error.302] type must be string, but is object", json::type_error&);
+ CHECK_THROWS_WITH_AS(
+ json(json::value_t::array).get<json::string_t>(),
+ "[json.exception.type_error.302] type must be string, but is array", json::type_error&);
+ CHECK_THROWS_WITH_AS(json(json::value_t::boolean).get<json::string_t>(),
+ "[json.exception.type_error.302] type must be string, "
+ "but is boolean", json::type_error&);
+ CHECK_THROWS_WITH_AS(
+ json(json::value_t::number_integer).get<json::string_t>(),
+ "[json.exception.type_error.302] type must be string, but is number", json::type_error&);
+ CHECK_THROWS_WITH_AS(
+ json(json::value_t::number_unsigned).get<json::string_t>(),
+ "[json.exception.type_error.302] type must be string, but is number", json::type_error&);
+ CHECK_THROWS_WITH_AS(
+ json(json::value_t::number_float).get<json::string_t>(),
+ "[json.exception.type_error.302] type must be string, but is number", json::type_error&);
+ }
+
+#if defined(JSON_HAS_CPP_17)
+ SECTION("exception in case of a non-string type using string_view")
+ {
+ CHECK_THROWS_WITH_AS(json(json::value_t::null).get<std::string_view>(),
+ "[json.exception.type_error.302] type must be string, but is null", json::type_error&);
+ CHECK_THROWS_WITH_AS(json(json::value_t::object).get<std::string_view>(),
+ "[json.exception.type_error.302] type must be string, but is object", json::type_error&);
+ CHECK_THROWS_WITH_AS(json(json::value_t::array).get<std::string_view>(),
+ "[json.exception.type_error.302] type must be string, but is array", json::type_error&);
+ CHECK_THROWS_WITH_AS(json(json::value_t::boolean).get<std::string_view>(),
+ "[json.exception.type_error.302] type must be string, but is boolean", json::type_error&);
+ CHECK_THROWS_WITH_AS(json(json::value_t::number_integer).get<std::string_view>(),
+ "[json.exception.type_error.302] type must be string, but is number", json::type_error&);
+ CHECK_THROWS_WITH_AS(json(json::value_t::number_unsigned).get<std::string_view>(),
+ "[json.exception.type_error.302] type must be string, but is number", json::type_error&);
+ CHECK_THROWS_WITH_AS(json(json::value_t::number_float).get<std::string_view>(),
+ "[json.exception.type_error.302] type must be string, but is number", json::type_error&);
+ }
+#endif
+ }
+
+ SECTION("get a string (explicit, get_to)")
+ {
+ const json::string_t s_reference{"Hello world"};
+ json j(s_reference);
+
+ SECTION("string_t")
+ {
+ json::string_t s = "previous value";
+ j.get_to(s);
+ CHECK(json(s) == j);
+ }
+
+ SECTION("std::string")
+ {
+ std::string s = "previous value";
+ j.get_to(s);
+ CHECK(json(s) == j);
+ }
+#if defined(JSON_HAS_CPP_17)
+ SECTION("std::string_view")
+ {
+ std::string const s = "previous value";
+ std::string_view sv = s;
+ j.get_to(sv);
+ CHECK(json(sv) == j);
+ }
+#endif
+ }
+
+ SECTION("get null (explicit)")
+ {
+ std::nullptr_t n = nullptr;
+ const json j(n);
+
+ auto n2 = j.get<std::nullptr_t>();
+ CHECK(n2 == n);
+
+ CHECK_THROWS_WITH_AS(json(json::value_t::string).get<std::nullptr_t>(),
+ "[json.exception.type_error.302] type must be null, but is string", json::type_error&);
+ CHECK_THROWS_WITH_AS(json(json::value_t::object).get<std::nullptr_t>(),
+ "[json.exception.type_error.302] type must be null, but is object", json::type_error&);
+ CHECK_THROWS_WITH_AS(json(json::value_t::array).get<std::nullptr_t>(),
+ "[json.exception.type_error.302] type must be null, but is array", json::type_error&);
+ CHECK_THROWS_WITH_AS(json(json::value_t::boolean).get<std::nullptr_t>(),
+ "[json.exception.type_error.302] type must be null, but is boolean", json::type_error&);
+ CHECK_THROWS_WITH_AS(json(json::value_t::number_integer).get<std::nullptr_t>(),
+ "[json.exception.type_error.302] type must be null, but is number", json::type_error&);
+ CHECK_THROWS_WITH_AS(json(json::value_t::number_unsigned).get<std::nullptr_t>(),
+ "[json.exception.type_error.302] type must be null, but is number", json::type_error&);
+ CHECK_THROWS_WITH_AS(json(json::value_t::number_float).get<std::nullptr_t>(),
+ "[json.exception.type_error.302] type must be null, but is number", json::type_error&);
+ }
+
+#if JSON_USE_IMPLICIT_CONVERSIONS
+ SECTION("get a string (implicit)")
+ {
+ const json::string_t s_reference{"Hello world"};
+ json j(s_reference);
+
+ SECTION("string_t")
+ {
+ const json::string_t s = j;
+ CHECK(json(s) == j);
+ }
+
+#if defined(JSON_HAS_CPP_17)
+ SECTION("std::string_view")
+ {
+ std::string_view const s = j.get<std::string_view>();
+ CHECK(json(s) == j);
+ }
+#endif
+
+ SECTION("std::string")
+ {
+ const std::string s = j;
+ CHECK(json(s) == j);
+ }
+ }
+#endif
+
+ SECTION("get a boolean (explicit)")
+ {
+ const json::boolean_t b_reference{true};
+ json j(b_reference);
+
+ SECTION("boolean_t")
+ {
+ auto b = j.get<json::boolean_t>();
+ CHECK(json(b) == j);
+ }
+
+ SECTION("uint8_t")
+ {
+ auto n = j.get<uint8_t>();
+ CHECK(n == 1);
+ }
+
+ SECTION("bool")
+ {
+ const bool b = j.get<bool>();
+ CHECK(json(b) == j);
+ }
+
+ SECTION("exception in case of a non-number type")
+ {
+ CHECK_THROWS_AS(json(json::value_t::string).get<uint8_t>(),
+ json::type_error&);
+
+ CHECK_THROWS_WITH_AS(
+ json(json::value_t::null).get<json::boolean_t>(),
+ "[json.exception.type_error.302] type must be boolean, but is null", json::type_error&);
+ CHECK_THROWS_WITH_AS(json(json::value_t::object).get<json::boolean_t>(),
+ "[json.exception.type_error.302] type must be boolean, "
+ "but is object", json::type_error&);
+ CHECK_THROWS_WITH_AS(
+ json(json::value_t::array).get<json::boolean_t>(),
+ "[json.exception.type_error.302] type must be boolean, but is array", json::type_error&);
+ CHECK_THROWS_WITH_AS(json(json::value_t::string).get<json::boolean_t>(),
+ "[json.exception.type_error.302] type must be boolean, "
+ "but is string", json::type_error&);
+ CHECK_THROWS_WITH_AS(
+ json(json::value_t::number_integer).get<json::boolean_t>(),
+ "[json.exception.type_error.302] type must be boolean, but is "
+ "number", json::type_error&);
+ CHECK_THROWS_WITH_AS(
+ json(json::value_t::number_unsigned).get<json::boolean_t>(),
+ "[json.exception.type_error.302] type must be boolean, but is "
+ "number", json::type_error&);
+ CHECK_THROWS_WITH_AS(
+ json(json::value_t::number_float).get<json::boolean_t>(),
+ "[json.exception.type_error.302] type must be boolean, but is "
+ "number", json::type_error&);
+ }
+ }
+
+#if JSON_USE_IMPLICIT_CONVERSIONS
+ SECTION("get a boolean (implicit)")
+ {
+ const json::boolean_t b_reference{true};
+ json j(b_reference);
+
+ SECTION("boolean_t")
+ {
+ const json::boolean_t b = j;
+ CHECK(json(b) == j);
+ }
+
+ SECTION("bool")
+ {
+ const bool b = j;
+ CHECK(json(b) == j);
+ }
+ }
+#endif
+
+ SECTION("get an integer number (explicit)")
+ {
+ const json::number_integer_t n_reference{42};
+ json j(n_reference);
+ const json::number_unsigned_t n_unsigned_reference{42u};
+ json j_unsigned(n_unsigned_reference);
+
+ SECTION("number_integer_t")
+ {
+ auto n = j.get<json::number_integer_t>();
+ CHECK(json(n) == j);
+ }
+
+ SECTION("number_unsigned_t")
+ {
+ auto n = j_unsigned.get<json::number_unsigned_t>();
+ CHECK(json(n) == j_unsigned);
+ }
+
+ SECTION("short")
+ {
+ auto n = j.get<short>();
+ CHECK(json(n) == j);
+ }
+
+ SECTION("unsigned short")
+ {
+ auto n = j.get<unsigned short>();
+ CHECK(json(n) == j);
+ }
+
+ SECTION("int")
+ {
+ const int n = j.get<int>();
+ CHECK(json(n) == j);
+ }
+
+ SECTION("unsigned int")
+ {
+ auto n = j.get<unsigned int>();
+ CHECK(json(n) == j);
+ }
+
+ SECTION("long")
+ {
+ const long n = j.get<long>();
+ CHECK(json(n) == j);
+ }
+
+ SECTION("unsigned long")
+ {
+ auto n = j.get<unsigned long>();
+ CHECK(json(n) == j);
+ }
+
+ SECTION("long long")
+ {
+ auto n = j.get<long long>();
+ CHECK(json(n) == j);
+ }
+
+ SECTION("unsigned long long")
+ {
+ auto n = j.get<unsigned long long>();
+ CHECK(json(n) == j);
+ }
+
+ SECTION("int8_t")
+ {
+ auto n = j.get<int8_t>();
+ CHECK(json(n) == j);
+ }
+
+ SECTION("int16_t")
+ {
+ auto n = j.get<int16_t>();
+ CHECK(json(n) == j);
+ }
+
+ SECTION("int32_t")
+ {
+ auto n = j.get<int32_t>();
+ CHECK(json(n) == j);
+ }
+
+ SECTION("int64_t")
+ {
+ auto n = j.get<int64_t>();
+ CHECK(json(n) == j);
+ }
+
+ SECTION("int8_fast_t")
+ {
+ auto n = j.get<int_fast8_t>();
+ CHECK(json(n) == j);
+ }
+
+ SECTION("int16_fast_t")
+ {
+ auto n = j.get<int_fast16_t>();
+ CHECK(json(n) == j);
+ }
+
+ SECTION("int32_fast_t")
+ {
+ auto n = j.get<int_fast32_t>();
+ CHECK(json(n) == j);
+ }
+
+ SECTION("int64_fast_t")
+ {
+ auto n = j.get<int_fast64_t>();
+ CHECK(json(n) == j);
+ }
+
+ SECTION("int8_least_t")
+ {
+ auto n = j.get<int_least8_t>();
+ CHECK(json(n) == j);
+ }
+
+ SECTION("int16_least_t")
+ {
+ auto n = j.get<int_least16_t>();
+ CHECK(json(n) == j);
+ }
+
+ SECTION("int32_least_t")
+ {
+ auto n = j.get<int_least32_t>();
+ CHECK(json(n) == j);
+ }
+
+ SECTION("int64_least_t")
+ {
+ auto n = j.get<int_least64_t>();
+ CHECK(json(n) == j);
+ }
+
+ SECTION("uint8_t")
+ {
+ auto n = j.get<uint8_t>();
+ CHECK(json(n) == j);
+ }
+
+ SECTION("uint16_t")
+ {
+ auto n = j.get<uint16_t>();
+ CHECK(json(n) == j);
+ }
+
+ SECTION("uint32_t")
+ {
+ auto n = j.get<uint32_t>();
+ CHECK(json(n) == j);
+ }
+
+ SECTION("uint64_t")
+ {
+ auto n = j.get<uint64_t>();
+ CHECK(json(n) == j);
+ }
+
+ SECTION("uint8_fast_t")
+ {
+ auto n = j.get<uint_fast8_t>();
+ CHECK(json(n) == j);
+ }
+
+ SECTION("uint16_fast_t")
+ {
+ auto n = j.get<uint_fast16_t>();
+ CHECK(json(n) == j);
+ }
+
+ SECTION("uint32_fast_t")
+ {
+ auto n = j.get<uint_fast32_t>();
+ CHECK(json(n) == j);
+ }
+
+ SECTION("uint64_fast_t")
+ {
+ auto n = j.get<uint_fast64_t>();
+ CHECK(json(n) == j);
+ }
+
+ SECTION("uint8_least_t")
+ {
+ auto n = j.get<uint_least8_t>();
+ CHECK(json(n) == j);
+ }
+
+ SECTION("uint16_least_t")
+ {
+ auto n = j.get<uint_least16_t>();
+ CHECK(json(n) == j);
+ }
+
+ SECTION("uint32_least_t")
+ {
+ auto n = j.get<uint_least32_t>();
+ CHECK(json(n) == j);
+ }
+
+ SECTION("uint64_least_t")
+ {
+ auto n = j.get<uint_least64_t>();
+ CHECK(json(n) == j);
+ }
+
+ SECTION("exception in case of a non-number type")
+ {
+ CHECK_THROWS_WITH_AS(
+ json(json::value_t::null).get<json::number_integer_t>(),
+ "[json.exception.type_error.302] type must be number, but is null", json::type_error&);
+ CHECK_THROWS_WITH_AS(
+ json(json::value_t::object).get<json::number_integer_t>(),
+ "[json.exception.type_error.302] type must be number, but is object", json::type_error&);
+ CHECK_THROWS_WITH_AS(
+ json(json::value_t::array).get<json::number_integer_t>(),
+ "[json.exception.type_error.302] type must be number, but is array", json::type_error&);
+ CHECK_THROWS_WITH_AS(
+ json(json::value_t::string).get<json::number_integer_t>(),
+ "[json.exception.type_error.302] type must be number, but is string", json::type_error&);
+ CHECK_THROWS_WITH_AS(
+ json(json::value_t::boolean).get<json::number_integer_t>(),
+ "[json.exception.type_error.302] type must be number, but is "
+ "boolean", json::type_error&);
+
+ CHECK_NOTHROW(
+ json(json::value_t::number_float).get<json::number_integer_t>());
+ CHECK_NOTHROW(
+ json(json::value_t::number_float).get<json::number_unsigned_t>());
+ }
+ }
+
+#if JSON_USE_IMPLICIT_CONVERSIONS
+ SECTION("get an integer number (implicit)")
+ {
+ json::number_integer_t const n_reference{42};
+ json j(n_reference);
+ json::number_unsigned_t const n_unsigned_reference{42u};
+ json j_unsigned(n_unsigned_reference);
+
+ SECTION("number_integer_t")
+ {
+ auto n = j.get<json::number_integer_t>();
+ CHECK(json(n) == j);
+ }
+
+ SECTION("number_unsigned_t")
+ {
+ auto n = j_unsigned.get<json::number_unsigned_t>();
+ CHECK(json(n) == j_unsigned);
+ }
+
+ SECTION("short")
+ {
+ short const n = j;
+ CHECK(json(n) == j);
+ }
+
+ SECTION("unsigned short")
+ {
+ unsigned short const n = j_unsigned;
+ CHECK(json(n) == j_unsigned);
+ }
+
+ SECTION("int")
+ {
+ int const n = j;
+ CHECK(json(n) == j);
+ }
+
+ SECTION("unsigned int")
+ {
+ unsigned int const n = j_unsigned;
+ CHECK(json(n) == j_unsigned);
+ }
+
+ SECTION("long")
+ {
+ long const n = j;
+ CHECK(json(n) == j);
+ }
+
+ SECTION("unsigned long")
+ {
+ unsigned long const n = j_unsigned;
+ CHECK(json(n) == j_unsigned);
+ }
+
+ SECTION("long long")
+ {
+ long long const n = j;
+ CHECK(json(n) == j);
+ }
+
+ SECTION("unsigned long long")
+ {
+ unsigned long long const n = j_unsigned;
+ CHECK(json(n) == j_unsigned);
+ }
+
+ SECTION("int8_t")
+ {
+ int8_t const n = j;
+ CHECK(json(n) == j);
+ }
+
+ SECTION("int16_t")
+ {
+ int16_t const n = j;
+ CHECK(json(n) == j);
+ }
+
+ SECTION("int32_t")
+ {
+ int32_t const n = j;
+ CHECK(json(n) == j);
+ }
+
+ SECTION("int64_t")
+ {
+ int64_t const n = j;
+ CHECK(json(n) == j);
+ }
+
+ SECTION("int8_fast_t")
+ {
+ int_fast8_t const n = j;
+ CHECK(json(n) == j);
+ }
+
+ SECTION("int16_fast_t")
+ {
+ int_fast16_t const n = j;
+ CHECK(json(n) == j);
+ }
+
+ SECTION("int32_fast_t")
+ {
+ int_fast32_t const n = j;
+ CHECK(json(n) == j);
+ }
+
+ SECTION("int64_fast_t")
+ {
+ int_fast64_t const n = j;
+ CHECK(json(n) == j);
+ }
+
+ SECTION("int8_least_t")
+ {
+ int_least8_t const n = j;
+ CHECK(json(n) == j);
+ }
+
+ SECTION("int16_least_t")
+ {
+ int_least16_t const n = j;
+ CHECK(json(n) == j);
+ }
+
+ SECTION("int32_least_t")
+ {
+ int_least32_t const n = j;
+ CHECK(json(n) == j);
+ }
+
+ SECTION("int64_least_t")
+ {
+ int_least64_t const n = j;
+ CHECK(json(n) == j);
+ }
+
+ SECTION("uint8_t")
+ {
+ uint8_t const n = j_unsigned;
+ CHECK(json(n) == j_unsigned);
+ }
+
+ SECTION("uint16_t")
+ {
+ uint16_t const n = j_unsigned;
+ CHECK(json(n) == j_unsigned);
+ }
+
+ SECTION("uint32_t")
+ {
+ uint32_t const n = j_unsigned;
+ CHECK(json(n) == j_unsigned);
+ }
+
+ SECTION("uint64_t")
+ {
+ uint64_t const n = j_unsigned;
+ CHECK(json(n) == j_unsigned);
+ }
+
+ SECTION("uint8_fast_t")
+ {
+ uint_fast8_t const n = j_unsigned;
+ CHECK(json(n) == j_unsigned);
+ }
+
+ SECTION("uint16_fast_t")
+ {
+ uint_fast16_t const n = j_unsigned;
+ CHECK(json(n) == j_unsigned);
+ }
+
+ SECTION("uint32_fast_t")
+ {
+ uint_fast32_t const n = j_unsigned;
+ CHECK(json(n) == j_unsigned);
+ }
+
+ SECTION("uint64_fast_t")
+ {
+ uint_fast64_t const n = j_unsigned;
+ CHECK(json(n) == j_unsigned);
+ }
+
+ SECTION("uint8_least_t")
+ {
+ uint_least8_t const n = j_unsigned;
+ CHECK(json(n) == j_unsigned);
+ }
+
+ SECTION("uint16_least_t")
+ {
+ uint_least16_t const n = j_unsigned;
+ CHECK(json(n) == j_unsigned);
+ }
+
+ SECTION("uint32_least_t")
+ {
+ uint_least32_t const n = j_unsigned;
+ CHECK(json(n) == j_unsigned);
+ }
+
+ SECTION("uint64_least_t")
+ {
+ uint_least64_t const n = j_unsigned;
+ CHECK(json(n) == j_unsigned);
+ }
+ }
+#endif
+
+ SECTION("get a floating-point number (explicit)")
+ {
+ json::number_float_t const n_reference{42.23};
+ json const j(n_reference);
+
+ SECTION("number_float_t")
+ {
+ auto n = j.get<json::number_float_t>();
+ CHECK(json(n).m_data.m_value.number_float == Approx(j.m_data.m_value.number_float));
+ }
+
+ SECTION("float")
+ {
+ auto n = j.get<float>();
+ CHECK(json(n).m_data.m_value.number_float == Approx(j.m_data.m_value.number_float));
+ }
+
+ SECTION("double")
+ {
+ auto n = j.get<double>();
+ CHECK(json(n).m_data.m_value.number_float == Approx(j.m_data.m_value.number_float));
+ }
+
+ SECTION("exception in case of a non-string type")
+ {
+ CHECK_THROWS_WITH_AS(
+ json(json::value_t::null).get<json::number_float_t>(),
+ "[json.exception.type_error.302] type must be number, but is null", json::type_error&);
+ CHECK_THROWS_WITH_AS(
+ json(json::value_t::object).get<json::number_float_t>(),
+ "[json.exception.type_error.302] type must be number, but is object", json::type_error&);
+ CHECK_THROWS_WITH_AS(
+ json(json::value_t::array).get<json::number_float_t>(),
+ "[json.exception.type_error.302] type must be number, but is array", json::type_error&);
+ CHECK_THROWS_WITH_AS(
+ json(json::value_t::string).get<json::number_float_t>(),
+ "[json.exception.type_error.302] type must be number, but is string", json::type_error&);
+ CHECK_THROWS_WITH_AS(
+ json(json::value_t::boolean).get<json::number_float_t>(),
+ "[json.exception.type_error.302] type must be number, but is "
+ "boolean", json::type_error&);
+
+ CHECK_NOTHROW(
+ json(json::value_t::number_integer).get<json::number_float_t>());
+ CHECK_NOTHROW(
+ json(json::value_t::number_unsigned).get<json::number_float_t>());
+ }
+ }
+
+#if JSON_USE_IMPLICIT_CONVERSIONS
+ SECTION("get a floating-point number (implicit)")
+ {
+ json::number_float_t const n_reference{42.23};
+ json const j(n_reference);
+
+ SECTION("number_float_t")
+ {
+ json::number_float_t const n = j;
+ CHECK(json(n).m_data.m_value.number_float == Approx(j.m_data.m_value.number_float));
+ }
+
+ SECTION("float")
+ {
+ float const n = j;
+ CHECK(json(n).m_data.m_value.number_float == Approx(j.m_data.m_value.number_float));
+ }
+
+ SECTION("double")
+ {
+ double const n = j;
+ CHECK(json(n).m_data.m_value.number_float == Approx(j.m_data.m_value.number_float));
+ }
+ }
+#endif
+
+ SECTION("get a binary value (explicit)")
+ {
+ json::binary_t const n_reference{{1, 2, 3}};
+ json j(n_reference);
+
+ SECTION("binary_t")
+ {
+ json::binary_t const b = j.get<json::binary_t>();
+ CHECK(*json(b).m_data.m_value.binary == *j.m_data.m_value.binary);
+ }
+
+ SECTION("get_binary()")
+ {
+ SECTION("non-const")
+ {
+ auto& b = j.get_binary();
+ CHECK(*json(b).m_data.m_value.binary == *j.m_data.m_value.binary);
+ }
+
+ SECTION("non-const")
+ {
+ const json j_const = j; // NOLINT(performance-unnecessary-copy-initialization)
+ const auto& b = j_const.get_binary();
+ CHECK(*json(b).m_data.m_value.binary == *j.m_data.m_value.binary);
+ }
+ }
+
+ SECTION("exception in case of a non-string type")
+ {
+ json j_null(json::value_t::null);
+ json j_object(json::value_t::object);
+ json j_array(json::value_t::array);
+ json j_string(json::value_t::string);
+ json j_boolean(json::value_t::boolean);
+ const json j_null_const(json::value_t::null);
+ const json j_object_const(json::value_t::object);
+ const json j_array_const(json::value_t::array);
+ const json j_string_const(json::value_t::string);
+ const json j_boolean_const(json::value_t::boolean);
+
+ CHECK_THROWS_WITH_AS(j_null.get<json::binary_t>(),
+ "[json.exception.type_error.302] type must be binary, but is null",
+ json::type_error&);
+ CHECK_THROWS_WITH_AS(j_object.get<json::binary_t>(),
+ "[json.exception.type_error.302] type must be binary, but is object",
+ json::type_error&);
+ CHECK_THROWS_WITH_AS(j_array.get<json::binary_t>(),
+ "[json.exception.type_error.302] type must be binary, but is array",
+ json::type_error&);
+ CHECK_THROWS_WITH_AS(j_string.get<json::binary_t>(),
+ "[json.exception.type_error.302] type must be binary, but is string",
+ json::type_error&);
+ CHECK_THROWS_WITH_AS(j_boolean.get<json::binary_t>(),
+ "[json.exception.type_error.302] type must be binary, but is boolean",
+ json::type_error&);
+
+ CHECK_THROWS_WITH_AS(j_null_const.get<json::binary_t>(),
+ "[json.exception.type_error.302] type must be binary, but is null",
+ json::type_error&);
+ CHECK_THROWS_WITH_AS(j_object_const.get<json::binary_t>(),
+ "[json.exception.type_error.302] type must be binary, but is object",
+ json::type_error&);
+ CHECK_THROWS_WITH_AS(j_array_const.get<json::binary_t>(),
+ "[json.exception.type_error.302] type must be binary, but is array",
+ json::type_error&);
+ CHECK_THROWS_WITH_AS(j_string_const.get<json::binary_t>(),
+ "[json.exception.type_error.302] type must be binary, but is string",
+ json::type_error&);
+ CHECK_THROWS_WITH_AS(j_boolean_const.get<json::binary_t>(),
+ "[json.exception.type_error.302] type must be binary, but is boolean",
+ json::type_error&);
+
+ CHECK_THROWS_WITH_AS(j_null.get_binary(),
+ "[json.exception.type_error.302] type must be binary, but is null",
+ json::type_error&);
+ CHECK_THROWS_WITH_AS(j_object.get_binary(),
+ "[json.exception.type_error.302] type must be binary, but is object",
+ json::type_error&);
+ CHECK_THROWS_WITH_AS(j_array.get_binary(),
+ "[json.exception.type_error.302] type must be binary, but is array",
+ json::type_error&);
+ CHECK_THROWS_WITH_AS(j_string.get_binary(),
+ "[json.exception.type_error.302] type must be binary, but is string",
+ json::type_error&);
+ CHECK_THROWS_WITH_AS(j_boolean.get_binary(),
+ "[json.exception.type_error.302] type must be binary, but is boolean",
+ json::type_error&);
+
+ CHECK_THROWS_WITH_AS(j_null_const.get_binary(),
+ "[json.exception.type_error.302] type must be binary, but is null",
+ json::type_error&);
+ CHECK_THROWS_WITH_AS(j_object_const.get_binary(),
+ "[json.exception.type_error.302] type must be binary, but is object",
+ json::type_error&);
+ CHECK_THROWS_WITH_AS(j_array_const.get_binary(),
+ "[json.exception.type_error.302] type must be binary, but is array",
+ json::type_error&);
+ CHECK_THROWS_WITH_AS(j_string_const.get_binary(),
+ "[json.exception.type_error.302] type must be binary, but is string",
+ json::type_error&);
+ CHECK_THROWS_WITH_AS(j_boolean_const.get_binary(),
+ "[json.exception.type_error.302] type must be binary, but is boolean",
+ json::type_error&);
+ }
+ }
+
+#if JSON_USE_IMPLICIT_CONVERSIONS
+ SECTION("get a binary value (implicit)")
+ {
+ json::binary_t const n_reference{{1, 2, 3}};
+ json const j(n_reference);
+
+ SECTION("binary_t")
+ {
+ json::binary_t const b = j;
+ CHECK(*json(b).m_data.m_value.binary == *j.m_data.m_value.binary);
+ }
+ }
+#endif
+
+#ifndef SKIP_TESTS_FOR_ENUM_SERIALIZATION
+ SECTION("get an enum")
+ {
+ enum c_enum { value_1, value_2 }; // NOLINT(cppcoreguidelines-use-enum-class)
+ enum class cpp_enum { value_1, value_2 };
+
+ CHECK(json(value_1).get<c_enum>() == value_1);
+ CHECK(json(cpp_enum::value_1).get<cpp_enum>() == cpp_enum::value_1);
+ }
+#endif
+
+ SECTION("more involved conversions")
+ {
+ SECTION("object-like STL containers")
+ {
+ json const j1 = {{"one", 1}, {"two", 2}, {"three", 3}};
+ json const j2 = {{"one", 1u}, {"two", 2u}, {"three", 3u}};
+ json const j3 = {{"one", 1.1}, {"two", 2.2}, {"three", 3.3}};
+ json const j4 = {{"one", true}, {"two", false}, {"three", true}};
+ json const j5 = {{"one", "eins"}, {"two", "zwei"}, {"three", "drei"}};
+
+ SECTION("std::map")
+ {
+ j1.get<std::map<std::string, int>>();
+ j2.get<std::map<std::string, unsigned int>>();
+ j3.get<std::map<std::string, double>>();
+ j4.get<std::map<std::string, bool>>();
+ j5.get<std::map<std::string, std::string>>();
+ }
+
+ SECTION("std::unordered_map")
+ {
+ j1.get<std::unordered_map<std::string, int>>();
+ j2.get<std::unordered_map<std::string, unsigned int>>();
+ j3.get<std::unordered_map<std::string, double>>();
+ j4.get<std::unordered_map<std::string, bool>>();
+ j5.get<std::unordered_map<std::string, std::string>>();
+ // CHECK(m5["one"] == "eins");
+ }
+
+ SECTION("std::multimap")
+ {
+ j1.get<std::multimap<std::string, int>>();
+ j2.get<std::multimap<std::string, unsigned int>>();
+ j3.get<std::multimap<std::string, double>>();
+ j4.get<std::multimap<std::string, bool>>();
+ j5.get<std::multimap<std::string, std::string>>();
+ // CHECK(m5["one"] == "eins");
+ }
+
+ SECTION("std::unordered_multimap")
+ {
+ j1.get<std::unordered_multimap<std::string, int>>();
+ j2.get<std::unordered_multimap<std::string, unsigned int>>();
+ j3.get<std::unordered_multimap<std::string, double>>();
+ j4.get<std::unordered_multimap<std::string, bool>>();
+ j5.get<std::unordered_multimap<std::string, std::string>>();
+ // CHECK(m5["one"] == "eins");
+ }
+
+ SECTION("exception in case of a non-object type")
+ {
+ CHECK_THROWS_WITH_AS(
+ (json().get<std::map<std::string, int>>()),
+ "[json.exception.type_error.302] type must be object, but is null", json::type_error&);
+ }
+ }
+
+ SECTION("array-like STL containers")
+ {
+ json const j1 = {1, 2, 3, 4};
+ json const j2 = {1u, 2u, 3u, 4u};
+ json const j3 = {1.2, 2.3, 3.4, 4.5};
+ json const j4 = {true, false, true};
+ json const j5 = {"one", "two", "three"};
+
+ SECTION("std::list")
+ {
+ j1.get<std::list<int>>();
+ j2.get<std::list<unsigned int>>();
+ j3.get<std::list<double>>();
+ j4.get<std::list<bool>>();
+ j5.get<std::list<std::string>>();
+ }
+
+ SECTION("std::forward_list")
+ {
+ j1.get<std::forward_list<int>>();
+ j2.get<std::forward_list<unsigned int>>();
+ j3.get<std::forward_list<double>>();
+ j4.get<std::forward_list<bool>>();
+ j5.get<std::forward_list<std::string>>();
+ }
+
+ SECTION("std::array")
+ {
+ j1.get<std::array<int, 4>>();
+ j2.get<std::array<unsigned int, 3>>();
+ j3.get<std::array<double, 4>>();
+ j4.get<std::array<bool, 3>>();
+ j5.get<std::array<std::string, 3>>();
+
+ SECTION("std::array is larger than JSON")
+ {
+ std::array<int, 6> arr6 = {{1, 2, 3, 4, 5, 6}};
+ CHECK_THROWS_WITH_AS(j1.get_to(arr6), "[json.exception.out_of_range.401] "
+ "array index 4 is out of range", json::out_of_range&);
+ }
+
+ SECTION("std::array is smaller than JSON")
+ {
+ std::array<int, 2> arr2 = {{8, 9}};
+ j1.get_to(arr2);
+ CHECK(arr2[0] == 1);
+ CHECK(arr2[1] == 2);
+ }
+ }
+
+ SECTION("std::valarray")
+ {
+ j1.get<std::valarray<int>>();
+ j2.get<std::valarray<unsigned int>>();
+ j3.get<std::valarray<double>>();
+ j4.get<std::valarray<bool>>();
+ j5.get<std::valarray<std::string>>();
+ }
+
+ SECTION("std::vector")
+ {
+ j1.get<std::vector<int>>();
+ j2.get<std::vector<unsigned int>>();
+ j3.get<std::vector<double>>();
+ j4.get<std::vector<bool>>();
+ j5.get<std::vector<std::string>>();
+ }
+
+ SECTION("std::deque")
+ {
+ j1.get<std::deque<int>>();
+ j2.get<std::deque<unsigned int>>();
+ j2.get<std::deque<double>>();
+ j4.get<std::deque<bool>>();
+ j5.get<std::deque<std::string>>();
+ }
+
+ SECTION("std::set")
+ {
+ j1.get<std::set<int>>();
+ j2.get<std::set<unsigned int>>();
+ j3.get<std::set<double>>();
+ j4.get<std::set<bool>>();
+ j5.get<std::set<std::string>>();
+ }
+
+ SECTION("std::unordered_set")
+ {
+ j1.get<std::unordered_set<int>>();
+ j2.get<std::unordered_set<unsigned int>>();
+ j3.get<std::unordered_set<double>>();
+ j4.get<std::unordered_set<bool>>();
+ j5.get<std::unordered_set<std::string>>();
+ }
+
+ SECTION("std::map (array of pairs)")
+ {
+ const std::map<int, int> m{{0, 1}, {1, 2}, {2, 3}};
+ json const j6 = m;
+
+ auto m2 = j6.get<std::map<int, int>>();
+ CHECK(m == m2);
+
+ json const j7 = {0, 1, 2, 3};
+ json const j8 = 2;
+ CHECK_THROWS_WITH_AS((j7.get<std::map<int, int>>()),
+ "[json.exception.type_error.302] type must be array, "
+ "but is number", json::type_error&);
+ CHECK_THROWS_WITH_AS((j8.get<std::map<int, int>>()),
+ "[json.exception.type_error.302] type must be array, "
+ "but is number", json::type_error&);
+
+ SECTION("superfluous entries")
+ {
+ json const j9 = {{0, 1, 2}, {1, 2, 3}, {2, 3, 4}};
+ m2 = j9.get<std::map<int, int>>();
+ CHECK(m == m2);
+ }
+ }
+
+ SECTION("std::unordered_map (array of pairs)")
+ {
+ const std::unordered_map<int, int> m{{0, 1}, {1, 2}, {2, 3}};
+ json const j6 = m;
+
+ auto m2 = j6.get<std::unordered_map<int, int>>();
+ CHECK(m == m2);
+
+ json const j7 = {0, 1, 2, 3};
+ json const j8 = 2;
+ CHECK_THROWS_WITH_AS((j7.get<std::unordered_map<int, int>>()),
+ "[json.exception.type_error.302] type must be array, "
+ "but is number", json::type_error&);
+ CHECK_THROWS_WITH_AS((j8.get<std::unordered_map<int, int>>()),
+ "[json.exception.type_error.302] type must be array, "
+ "but is number", json::type_error&);
+
+ SECTION("superfluous entries")
+ {
+ json const j9{{0, 1, 2}, {1, 2, 3}, {2, 3, 4}};
+ m2 = j9.get<std::unordered_map<int, int>>();
+ CHECK(m == m2);
+ }
+ }
+
+ SECTION("exception in case of a non-object type")
+ {
+ // does type really must be an array? or it rather must not be null?
+ // that's what I thought when other test like this one broke
+ CHECK_THROWS_WITH_AS(
+ (json().get<std::list<int>>()),
+ "[json.exception.type_error.302] type must be array, but is null", json::type_error&);
+ CHECK_THROWS_WITH_AS(
+ (json().get<std::vector<int>>()),
+ "[json.exception.type_error.302] type must be array, but is null", json::type_error&);
+ CHECK_THROWS_WITH_AS(
+ (json().get<std::vector<json>>()),
+ "[json.exception.type_error.302] type must be array, but is null", json::type_error&);
+ CHECK_THROWS_WITH_AS(
+ (json().get<std::list<json>>()),
+ "[json.exception.type_error.302] type must be array, but is null", json::type_error&);
+ CHECK_THROWS_WITH_AS(
+ (json().get<std::valarray<int>>()),
+ "[json.exception.type_error.302] type must be array, but is null", json::type_error&);
+ CHECK_THROWS_WITH_AS(
+ (json().get<std::map<int, int>>()),
+ "[json.exception.type_error.302] type must be array, but is null", json::type_error&);
+ }
+ }
+ }
+}
+
+enum class cards {kreuz, pik, herz, karo};
+
+// NOLINTNEXTLINE(misc-use-internal-linkage,misc-const-correctness,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) - false positive
+NLOHMANN_JSON_SERIALIZE_ENUM(cards,
+{
+ {cards::kreuz, "kreuz"},
+ {cards::pik, "pik"},
+ {cards::pik, "puk"}, // second entry for cards::puk; will not be used
+ {cards::herz, "herz"},
+ {cards::karo, "karo"}
+})
+
+enum TaskState // NOLINT(cert-int09-c,readability-enum-initial-value,cppcoreguidelines-use-enum-class)
+{
+ TS_STOPPED,
+ TS_RUNNING,
+ TS_COMPLETED,
+ TS_INVALID = -1,
+};
+
+// NOLINTNEXTLINE(misc-const-correctness,misc-use-internal-linkage,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) - false positive
+NLOHMANN_JSON_SERIALIZE_ENUM(TaskState,
+{
+ {TS_INVALID, nullptr},
+ {TS_STOPPED, "stopped"},
+ {TS_RUNNING, "running"},
+ {TS_COMPLETED, "completed"},
+})
+
+TEST_CASE("JSON to enum mapping")
+{
+ SECTION("enum class")
+ {
+ // enum -> json
+ CHECK(json(cards::kreuz) == "kreuz");
+ CHECK(json(cards::pik) == "pik");
+ CHECK(json(cards::herz) == "herz");
+ CHECK(json(cards::karo) == "karo");
+
+ // json -> enum
+ CHECK(cards::kreuz == json("kreuz"));
+ CHECK(cards::pik == json("pik"));
+ CHECK(cards::herz == json("herz"));
+ CHECK(cards::karo == json("karo"));
+
+ // invalid json -> first enum
+ CHECK(cards::kreuz == json("what?").get<cards>());
+ }
+
+ SECTION("traditional enum")
+ {
+ // enum -> json
+ CHECK(json(TS_STOPPED) == "stopped");
+ CHECK(json(TS_RUNNING) == "running");
+ CHECK(json(TS_COMPLETED) == "completed");
+ CHECK(json(TS_INVALID) == json());
+
+ // json -> enum
+ CHECK(TS_STOPPED == json("stopped"));
+ CHECK(TS_RUNNING == json("running"));
+ CHECK(TS_COMPLETED == json("completed"));
+ CHECK(TS_INVALID == json());
+
+ // invalid json -> first enum
+ CHECK(TS_INVALID == json("what?").get<TaskState>());
+ }
+}
+
+#ifdef JSON_HAS_CPP_17
+#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
+TEST_CASE("std::filesystem::path")
+{
+ SECTION("ascii")
+ {
+ json const j_string = "Path";
+ auto p = j_string.template get<nlohmann::detail::std_fs::path>();
+ json const j_path = p;
+
+ CHECK(j_path.template get<std::string>() ==
+ j_string.template get<std::string>());
+ }
+
+ SECTION("utf-8")
+ {
+ json const j_string = "P\xc4\x9b\xc5\xa1ina";
+ auto p = j_string.template get<nlohmann::detail::std_fs::path>();
+ json const j_path = p;
+
+ CHECK(j_path.template get<std::string>() ==
+ j_string.template get<std::string>());
+ }
+}
+#endif
+
+#ifndef JSON_USE_IMPLICIT_CONVERSIONS
+TEST_CASE("std::optional")
+{
+ SECTION("null")
+ {
+ json j_null;
+ std::optional<std::string> opt_null;
+
+ CHECK(json(opt_null) == j_null);
+ CHECK(j_null.get<std::optional<std::string>>() == std::nullopt);
+ }
+
+ SECTION("string")
+ {
+ json j_string = "string";
+ std::optional<std::string> opt_string = "string";
+
+ CHECK(json(opt_string) == j_string);
+ CHECK(std::optional<std::string>(j_string) == opt_string);
+ }
+
+ SECTION("bool")
+ {
+ json j_bool = true;
+ std::optional<bool> opt_bool = true;
+
+ CHECK(json(opt_bool) == j_bool);
+ CHECK(std::optional<bool>(j_bool) == opt_bool);
+ }
+
+ SECTION("number")
+ {
+ json j_number = 1;
+ std::optional<int> opt_int = 1;
+
+ CHECK(json(opt_int) == j_number);
+ CHECK(j_number.get<std::optional<int>>() == opt_int);
+ }
+
+ SECTION("array")
+ {
+ json j_array = {1, 2, nullptr};
+ std::vector<std::optional<int>> opt_array = {{1, 2, std::nullopt}};
+
+ CHECK(json(opt_array) == j_array);
+ CHECK(j_array.get<std::vector<std::optional<int>>>() == opt_array);
+ }
+
+ SECTION("object")
+ {
+ json j_object = {{"one", 1}, {"two", 2}, {"zero", nullptr}};
+ std::map<std::string, std::optional<int>> opt_object {{"one", 1}, {"two", 2}, {"zero", std::nullopt}};
+
+ CHECK(json(opt_object) == j_object);
+ CHECK(std::map<std::string, std::optional<int>>(j_object) == opt_object);
+ }
+}
+#endif
+#endif
+
+#ifdef JSON_HAS_CPP_17
+ #undef JSON_HAS_CPP_17
+#endif
+
+#ifdef JSON_HAS_CPP_14
+ #undef JSON_HAS_CPP_14
+#endif
+DOCTEST_CLANG_SUPPRESS_WARNING_POP