| // __ _____ _____ _____ |
| // __| | __| | | | JSON for Modern C++ (supporting code) |
| // | | |__ | | | | | | version 3.11.3 |
| // |_____|_____|_____|_|___| https://github.com/nlohmann/json |
| // |
| // Copyright (c) 2013-2022 Niels Lohmann <http://nlohmann.me>. |
| // SPDX-FileCopyrightText: 2013-2023 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" |
| |
| #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") |
| |
| 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(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) |
| const int nbs[] = { 0, 1, 2 }; // NOLINT(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(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("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; |
| 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 |
| |
| SECTION("get an enum") |
| { |
| enum c_enum |
| { |
| value_1, |
| value_2 |
| }; |
| 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); |
| } |
| |
| 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)") |
| { |
| 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)") |
| { |
| 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(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 |
| { |
| TS_STOPPED, |
| TS_RUNNING, |
| TS_COMPLETED, |
| TS_INVALID = -1, |
| }; |
| |
| // NOLINTNEXTLINE(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>()); |
| } |
| } |
| |
| DOCTEST_CLANG_SUPPRESS_WARNING_POP |