diff --git a/include/nlohmann/detail/conversions/from_json.hpp b/include/nlohmann/detail/conversions/from_json.hpp index b07be60606..363a649d50 100644 --- a/include/nlohmann/detail/conversions/from_json.hpp +++ b/include/nlohmann/detail/conversions/from_json.hpp @@ -539,7 +539,12 @@ inline void from_json(const BasicJsonType& j, std_fs::path& p) { JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j)); } - p = *j.template get_ptr(); + const auto& s = *j.template get_ptr(); +#ifdef JSON_HAS_CPP_20 + p = std_fs::path(std::u8string_view(reinterpret_cast(s.data()), s.size())); +#else + p = std_fs::u8path(s); // accepts UTF-8 encoded std::string in C++17, deprecated in C++20 +#endif } #endif diff --git a/include/nlohmann/detail/conversions/to_json.hpp b/include/nlohmann/detail/conversions/to_json.hpp index 06a8851c56..6bce764057 100644 --- a/include/nlohmann/detail/conversions/to_json.hpp +++ b/include/nlohmann/detail/conversions/to_json.hpp @@ -443,7 +443,12 @@ inline void to_json(BasicJsonType& j, const T& t) template inline void to_json(BasicJsonType& j, const std_fs::path& p) { - j = p.string(); +#ifdef JSON_HAS_CPP_20 + const std::u8string s = p.u8string(); + j = std::string(s.begin(), s.end()); +#else + j = p.u8string(); // returns std::string in C++17 +#endif } #endif diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 07dea3c4ab..5b7f87d218 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -5319,7 +5319,12 @@ inline void from_json(const BasicJsonType& j, std_fs::path& p) { JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j)); } - p = *j.template get_ptr(); + const auto& s = *j.template get_ptr(); +#ifdef JSON_HAS_CPP_20 + p = std_fs::path(std::u8string_view(reinterpret_cast(s.data()), s.size())); +#else + p = std_fs::u8path(s); // accepts UTF-8 encoded std::string in C++17, deprecated in C++20 +#endif } #endif @@ -6080,7 +6085,12 @@ inline void to_json(BasicJsonType& j, const T& t) template inline void to_json(BasicJsonType& j, const std_fs::path& p) { - j = p.string(); +#ifdef JSON_HAS_CPP_20 + const std::u8string s = p.u8string(); + j = std::string(s.begin(), s.end()); +#else + j = p.u8string(); // returns std::string in C++17 +#endif } #endif diff --git a/tests/src/unit-conversions.cpp b/tests/src/unit-conversions.cpp index 7aa4e2a468..b38ab39c9a 100644 --- a/tests/src/unit-conversions.cpp +++ b/tests/src/unit-conversions.cpp @@ -8,15 +8,16 @@ // cmake/test.cmake selects the C++ standard versions with which to build a // unit test based on the presence of JSON_HAS_CPP_ 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: +// 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_ (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) +#if defined(JSON_DISABLE_ENUM_SERIALIZATION) && \ + (JSON_DISABLE_ENUM_SERIALIZATION == 1) #define SKIP_TESTS_FOR_ENUM_SERIALIZATION #endif @@ -36,10 +37,12 @@ using nlohmann::json; 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 +#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) +#elif (defined(__cplusplus) && __cplusplus >= 201402L) || \ + (defined(_HAS_CXX14) && _HAS_CXX14 == 1) #define JSON_HAS_CPP_14 #endif @@ -106,25 +109,33 @@ TEST_CASE("value conversion") { CHECK_THROWS_WITH_AS( json(json::value_t::null).get(), - "[json.exception.type_error.302] type must be object, but is null", json::type_error&); + "[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.exception.type_error.302] type must be object, but is array", json::type_error&); + "[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.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.exception.type_error.302] type must be object, " - "but is boolean", json::type_error&); + "[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.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.exception.type_error.302] type must be object, but is number", json::type_error&); + "[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.exception.type_error.302] type must be object, but is number", json::type_error&); + "[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.exception.type_error.302] type must be object, but is number", json::type_error&); + "[json.exception.type_error.302] type must be object, but is number", + json::type_error&); } } @@ -245,7 +256,8 @@ TEST_CASE("value conversion") CHECK_THROWS_WITH_AS( json(json::value_t::null).get>(), - "[json.exception.type_error.302] type must be array, but is null", json::type_error&); + "[json.exception.type_error.302] type must be array, but is null", + json::type_error&); } SECTION("std::vector") @@ -255,7 +267,8 @@ TEST_CASE("value conversion") CHECK_THROWS_WITH_AS( json(json::value_t::null).get>(), - "[json.exception.type_error.302] type must be array, but is null", json::type_error&); + "[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") @@ -270,8 +283,13 @@ TEST_CASE("value conversion") 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 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; @@ -292,28 +310,36 @@ TEST_CASE("value conversion") { CHECK_THROWS_WITH_AS( json(json::value_t::object).get>(), - "[json.exception.type_error.302] type must be array, but is object", json::type_error&); + "[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.exception.type_error.302] type must be array, but is null", json::type_error&); + "[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.exception.type_error.302] type must be array, but is object", json::type_error&); + "[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.exception.type_error.302] type must be array, but is string", json::type_error&); + "[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.exception.type_error.302] type must be array, but is boolean", json::type_error&); + "[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.exception.type_error.302] type must be array, but is number", json::type_error&); + "[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.exception.type_error.302] type must be array, but is number", json::type_error&); + "[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.exception.type_error.302] type must be array, but is number", json::type_error&); + "[json.exception.type_error.302] type must be array, but is number", + json::type_error&); } } @@ -360,8 +386,16 @@ TEST_CASE("value conversion") 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 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); @@ -370,64 +404,75 @@ TEST_CASE("value conversion") SECTION("built-in arrays: 2D") { - const int nbs[][3] = {{0, 1, 2}, {3, 4, 5}}; // NOLINT(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 int nbs[][3] = + { + {0, 1, 2}, + { + 3, 4, + 5 + } + }; // NOLINT(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]))); + CHECK(std::equal(std::begin(nbs[0]), std::end(nbs[1]), + std::begin(nbs2[0]))); } SECTION("built-in arrays: 3D") { // NOLINTBEGIN(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}}\ + 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(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]))); + CHECK(std::equal(std::begin(nbs[0][0]), std::end(nbs[1][1]), + std::begin(nbs2[0][0]))); } SECTION("built-in arrays: 4D") { // NOLINTBEGIN(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) - const int nbs[][2][2][3] = {\ + const int nbs[][2][2][3] = + { { - \ - {{0, 1, 2}, {3, 4, 5}}, \ - {{10, 11, 12}, {13, 14, 15}}\ - }, \ + + {{0, 1, 2}, {3, 4, 5}}, {{10, 11, 12}, {13, 14, 15}} + }, { - \ - {{20, 21, 22}, {23, 24, 25}}, \ - {{30, 31, 32}, {33, 34, 35}}\ - }\ + + {{20, 21, 22}, {23, 24, 25}}, {{30, 31, 32}, {33, 34, 35}} + } }; - int nbs2[][2][2][3] = {\ + 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}} + }, { - \ - {{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(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]))); + CHECK(std::equal(std::begin(nbs[0][0][0]), std::end(nbs[1][1][1]), + std::begin(nbs2[0][0][0]))); } SECTION("std::deque") @@ -505,44 +550,66 @@ TEST_CASE("value conversion") { CHECK_THROWS_WITH_AS( json(json::value_t::null).get(), - "[json.exception.type_error.302] type must be string, but is null", json::type_error&); + "[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.exception.type_error.302] type must be string, but is object", json::type_error&); + "[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.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.exception.type_error.302] type must be string, " - "but is boolean", json::type_error&); + "[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.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.exception.type_error.302] type must be string, but is number", json::type_error&); + "[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.exception.type_error.302] type must be string, but is number", json::type_error&); + "[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.exception.type_error.302] type must be string, but is number", json::type_error&); + "[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(), - "[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.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.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.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.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.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.exception.type_error.302] type must be string, but is number", json::type_error&); + CHECK_THROWS_WITH_AS( + json(json::value_t::null).get(), + "[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.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.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.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.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.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.exception.type_error.302] type must be string, but is number", + json::type_error&); } #endif } @@ -584,20 +651,34 @@ TEST_CASE("value conversion") auto n2 = j.get(); CHECK(n2 == n); - CHECK_THROWS_WITH_AS(json(json::value_t::string).get(), - "[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(), - "[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(), - "[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(), - "[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(), - "[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(), - "[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(), - "[json.exception.type_error.302] type must be null, but is number", json::type_error&); + CHECK_THROWS_WITH_AS( + json(json::value_t::string).get(), + "[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(), + "[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(), + "[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(), + "[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(), + "[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(), + "[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(), + "[json.exception.type_error.302] type must be null, but is number", + json::type_error&); } #if JSON_USE_IMPLICIT_CONVERSIONS @@ -658,28 +739,37 @@ TEST_CASE("value conversion") CHECK_THROWS_WITH_AS( json(json::value_t::null).get(), - "[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.exception.type_error.302] type must be boolean, " - "but is object", json::type_error&); + "[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.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.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.exception.type_error.302] type must be boolean, " - "but is string", json::type_error&); + "[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.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.exception.type_error.302] type must be boolean, but is " - "number", json::type_error&); + "number", + json::type_error&); CHECK_THROWS_WITH_AS( json(json::value_t::number_unsigned).get(), "[json.exception.type_error.302] type must be boolean, but is " - "number", json::type_error&); + "number", + json::type_error&); CHECK_THROWS_WITH_AS( json(json::value_t::number_float).get(), "[json.exception.type_error.302] type must be boolean, but is " - "number", json::type_error&); + "number", + json::type_error&); } } @@ -918,20 +1008,25 @@ TEST_CASE("value conversion") { CHECK_THROWS_WITH_AS( json(json::value_t::null).get(), - "[json.exception.type_error.302] type must be number, but is null", json::type_error&); + "[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.exception.type_error.302] type must be number, but is object", json::type_error&); + "[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.exception.type_error.302] type must be number, but is array", json::type_error&); + "[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.exception.type_error.302] type must be number, but is string", json::type_error&); + "[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.exception.type_error.302] type must be number, but is " - "boolean", json::type_error&); + "boolean", + json::type_error&); CHECK_NOTHROW( json(json::value_t::number_float).get()); @@ -1162,39 +1257,47 @@ TEST_CASE("value conversion") SECTION("number_float_t") { auto n = j.get(); - CHECK(json(n).m_data.m_value.number_float == Approx(j.m_data.m_value.number_float)); + CHECK(json(n).m_data.m_value.number_float == + Approx(j.m_data.m_value.number_float)); } SECTION("float") { auto n = j.get(); - CHECK(json(n).m_data.m_value.number_float == Approx(j.m_data.m_value.number_float)); + CHECK(json(n).m_data.m_value.number_float == + Approx(j.m_data.m_value.number_float)); } SECTION("double") { auto n = j.get(); - CHECK(json(n).m_data.m_value.number_float == Approx(j.m_data.m_value.number_float)); + 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.exception.type_error.302] type must be number, but is null", json::type_error&); + "[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.exception.type_error.302] type must be number, but is object", json::type_error&); + "[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.exception.type_error.302] type must be number, but is array", json::type_error&); + "[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.exception.type_error.302] type must be number, but is string", json::type_error&); + "[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.exception.type_error.302] type must be number, but is " - "boolean", json::type_error&); + "boolean", + json::type_error&); CHECK_NOTHROW( json(json::value_t::number_integer).get()); @@ -1212,19 +1315,22 @@ TEST_CASE("value conversion") 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)); + 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)); + 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)); + CHECK(json(n).m_data.m_value.number_float == + Approx(j.m_data.m_value.number_float)); } } #endif @@ -1250,7 +1356,8 @@ TEST_CASE("value conversion") SECTION("non-const") { - const json j_const = j; // NOLINT(performance-unnecessary-copy-initialization) + 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); } @@ -1269,69 +1376,89 @@ TEST_CASE("value conversion") 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.exception.type_error.302] type must be binary, but is null", - json::type_error&); - CHECK_THROWS_WITH_AS(j_object.get(), - "[json.exception.type_error.302] type must be binary, but is object", - json::type_error&); - CHECK_THROWS_WITH_AS(j_array.get(), - "[json.exception.type_error.302] type must be binary, but is array", - json::type_error&); - CHECK_THROWS_WITH_AS(j_string.get(), - "[json.exception.type_error.302] type must be binary, but is string", - json::type_error&); - CHECK_THROWS_WITH_AS(j_boolean.get(), - "[json.exception.type_error.302] type must be binary, but is boolean", - json::type_error&); - - CHECK_THROWS_WITH_AS(j_null_const.get(), - "[json.exception.type_error.302] type must be binary, but is null", - json::type_error&); - CHECK_THROWS_WITH_AS(j_object_const.get(), - "[json.exception.type_error.302] type must be binary, but is object", - json::type_error&); - CHECK_THROWS_WITH_AS(j_array_const.get(), - "[json.exception.type_error.302] type must be binary, but is array", - json::type_error&); - CHECK_THROWS_WITH_AS(j_string_const.get(), - "[json.exception.type_error.302] type must be binary, but is string", - json::type_error&); - CHECK_THROWS_WITH_AS(j_boolean_const.get(), - "[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&); + CHECK_THROWS_WITH_AS( + j_null.get(), + "[json.exception.type_error.302] type must be binary, but is null", + json::type_error&); + CHECK_THROWS_WITH_AS( + j_object.get(), + "[json.exception.type_error.302] type must be binary, but is object", + json::type_error&); + CHECK_THROWS_WITH_AS( + j_array.get(), + "[json.exception.type_error.302] type must be binary, but is array", + json::type_error&); + CHECK_THROWS_WITH_AS( + j_string.get(), + "[json.exception.type_error.302] type must be binary, but is string", + json::type_error&); + CHECK_THROWS_WITH_AS( + j_boolean.get(), + "[json.exception.type_error.302] type must be binary, but is boolean", + json::type_error&); + + CHECK_THROWS_WITH_AS( + j_null_const.get(), + "[json.exception.type_error.302] type must be binary, but is null", + json::type_error&); + CHECK_THROWS_WITH_AS( + j_object_const.get(), + "[json.exception.type_error.302] type must be binary, but is object", + json::type_error&); + CHECK_THROWS_WITH_AS( + j_array_const.get(), + "[json.exception.type_error.302] type must be binary, but is array", + json::type_error&); + CHECK_THROWS_WITH_AS( + j_string_const.get(), + "[json.exception.type_error.302] type must be binary, but is string", + json::type_error&); + CHECK_THROWS_WITH_AS( + j_boolean_const.get(), + "[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&); } } @@ -1413,7 +1540,8 @@ TEST_CASE("value conversion") { CHECK_THROWS_WITH_AS( (json().get>()), - "[json.exception.type_error.302] type must be object, but is null", json::type_error&); + "[json.exception.type_error.302] type must be object, but is null", + json::type_error&); } } @@ -1454,8 +1582,10 @@ TEST_CASE("value conversion") SECTION("std::array is larger than JSON") { std::array 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&); + 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") @@ -1522,12 +1652,16 @@ TEST_CASE("value conversion") json const j7 = {0, 1, 2, 3}; json const j8 = 2; - CHECK_THROWS_WITH_AS((j7.get>()), - "[json.exception.type_error.302] type must be array, " - "but is number", json::type_error&); - CHECK_THROWS_WITH_AS((j8.get>()), - "[json.exception.type_error.302] type must be array, " - "but is number", json::type_error&); + CHECK_THROWS_WITH_AS( + (j7.get>()), + "[json.exception.type_error.302] type must be array, " + "but is number", + json::type_error&); + CHECK_THROWS_WITH_AS( + (j8.get>()), + "[json.exception.type_error.302] type must be array, " + "but is number", + json::type_error&); SECTION("superfluous entries") { @@ -1547,12 +1681,16 @@ TEST_CASE("value conversion") json const j7 = {0, 1, 2, 3}; json const j8 = 2; - CHECK_THROWS_WITH_AS((j7.get>()), - "[json.exception.type_error.302] type must be array, " - "but is number", json::type_error&); - CHECK_THROWS_WITH_AS((j8.get>()), - "[json.exception.type_error.302] type must be array, " - "but is number", json::type_error&); + CHECK_THROWS_WITH_AS( + (j7.get>()), + "[json.exception.type_error.302] type must be array, " + "but is number", + json::type_error&); + CHECK_THROWS_WITH_AS( + (j8.get>()), + "[json.exception.type_error.302] type must be array, " + "but is number", + json::type_error&); SECTION("superfluous entries") { @@ -1568,35 +1706,43 @@ TEST_CASE("value conversion") // that's what I thought when other test like this one broke CHECK_THROWS_WITH_AS( (json().get>()), - "[json.exception.type_error.302] type must be array, but is null", json::type_error&); + "[json.exception.type_error.302] type must be array, but is null", + json::type_error&); CHECK_THROWS_WITH_AS( (json().get>()), - "[json.exception.type_error.302] type must be array, but is null", json::type_error&); + "[json.exception.type_error.302] type must be array, but is null", + json::type_error&); CHECK_THROWS_WITH_AS( (json().get>()), - "[json.exception.type_error.302] type must be array, but is null", json::type_error&); + "[json.exception.type_error.302] type must be array, but is null", + json::type_error&); CHECK_THROWS_WITH_AS( (json().get>()), - "[json.exception.type_error.302] type must be array, but is null", json::type_error&); + "[json.exception.type_error.302] type must be array, but is null", + json::type_error&); CHECK_THROWS_WITH_AS( (json().get>()), - "[json.exception.type_error.302] type must be array, but is null", json::type_error&); + "[json.exception.type_error.302] type must be array, but is null", + json::type_error&); CHECK_THROWS_WITH_AS( (json().get>()), - "[json.exception.type_error.302] type must be array, but is null", json::type_error&); + "[json.exception.type_error.302] type must be array, but is null", + json::type_error&); } } } } -enum class cards {kreuz, pik, herz, karo}; +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, +// 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::pik, "puk"}, // second entry for cards::puk; will not be used {cards::herz, "herz"}, {cards::karo, "karo"} }) @@ -1609,7 +1755,8 @@ enum TaskState // NOLINT(cert-int09-c,readability-enum-initial-value) TS_INVALID = -1, }; -// NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) - false positive +// NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) +// - false positive NLOHMANN_JSON_SERIALIZE_ENUM(TaskState, { {TS_INVALID, nullptr}, @@ -1658,6 +1805,31 @@ TEST_CASE("JSON to enum mapping") } #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(); + json const j_path = p; + + CHECK(j_path.template get() == + j_string.template get()); + } + + SECTION("utf-8") + { + json const j_string = "P\xc4\x9b\xc5\xa1ina"; + auto p = j_string.template get(); + json const j_path = p; + + CHECK(j_path.template get() == + j_string.template get()); + } +} +#endif + #ifndef JSON_USE_IMPLICIT_CONVERSIONS TEST_CASE("std::optional") { @@ -1709,7 +1881,9 @@ TEST_CASE("std::optional") SECTION("object") { json j_object = {{"one", 1}, {"two", 2}, {"zero", nullptr}}; - std::map> opt_object {{"one", 1}, {"two", 2}, {"zero", std::nullopt}}; + std::map> opt_object + { + {"one", 1}, {"two", 2}, {"zero", std::nullopt}}; CHECK(json(opt_object) == j_object); CHECK(std::map>(j_object) == opt_object);