diff --git a/include/nlohmann/detail/macro_scope.hpp b/include/nlohmann/detail/macro_scope.hpp index 3a4eb79f4..9c35cc3b7 100644 --- a/include/nlohmann/detail/macro_scope.hpp +++ b/include/nlohmann/detail/macro_scope.hpp @@ -336,7 +336,7 @@ void templated_json_throw(ExceptionType exception) return ej_pair.second == j; \ }); \ if (it != std::end(m)) e = it->first; \ - else templated_json_throw(nlohmann::detail::out_of_range::create(410,"enum value out of range for " #ENUM_TYPE ": " + j.dump(), &j)); \ + else templated_json_throw(nlohmann::detail::out_of_range::create(410, nlohmann::detail::concat("enum value out of range for " #ENUM_TYPE ": ", j.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace)), &j)); \ } // Ugly macros to avoid uglier copy-paste when specializing basic_json. They diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index f1aad02ce..16c2cdca6 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -2749,7 +2749,7 @@ void templated_json_throw(ExceptionType exception) return ej_pair.second == j; \ }); \ if (it != std::end(m)) e = it->first; \ - else templated_json_throw(nlohmann::detail::out_of_range::create(410,"enum value out of range for " #ENUM_TYPE ": " + j.dump(), &j)); \ + else templated_json_throw(nlohmann::detail::out_of_range::create(410, nlohmann::detail::concat("enum value out of range for " #ENUM_TYPE ": ", j.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace)), &j)); \ } // Ugly macros to avoid uglier copy-paste when specializing basic_json. They diff --git a/tests/src/unit-alt-string.cpp b/tests/src/unit-alt-string.cpp index cddaadb7e..f95d2213c 100644 --- a/tests/src/unit-alt-string.cpp +++ b/tests/src/unit-alt-string.cpp @@ -174,6 +174,15 @@ bool operator<(const char* op1, const alt_string& op2) noexcept return op1 < op2.str_impl; } +enum class alt_color { red, green }; + +// 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_STRICT(alt_color, +{ + {alt_color::red, "red"}, + {alt_color::green, "green"}, +}) + TEST_CASE("alternative string type") { SECTION("binary formats") @@ -374,4 +383,19 @@ TEST_CASE("alternative string type") const auto j2 = j.flatten(); CHECK(j2.dump() == R"({"/foo/0":"bar","/foo/1":"baz"})"); } + + SECTION("strict enum") + { + // regression test for #5667: NLOHMANN_JSON_SERIALIZE_ENUM_STRICT's from_json + // built its exception message with "..." + j.dump(), which does not compile + // when j.dump() returns a custom string_t (here alt_string) instead of + // std::string + alt_json doc; + doc = "red"; + CHECK(doc.get() == alt_color::red); + + alt_json _; + doc = "blue"; + CHECK_THROWS_WITH_AS(_ = doc.get(), "[json.exception.out_of_range.410] enum value out of range for alt_color: \"blue\"", alt_json::out_of_range&); + } } diff --git a/tests/src/unit-conversions.cpp b/tests/src/unit-conversions.cpp index 0d53f2226..2fce40fa9 100644 --- a/tests/src/unit-conversions.cpp +++ b/tests/src/unit-conversions.cpp @@ -1748,6 +1748,12 @@ TEST_CASE("Strict JSON to enum mapping") // conversion of unmapped enum -> exception thrown CHECK_THROWS_WITH_AS(json(strict_cards::andere), "[json.exception.out_of_range.410] enum value out of range for strict_cards", json::out_of_range&); + + // invalid UTF-8 -> out_of_range.410, not the type_error.316 thrown while building the + // message (regression test for #5667); such strings can reach get() unvalidated, + // e.g. from from_cbor()/from_msgpack() (#5529) + const json j_invalid_utf8 = "\xFF"; + CHECK_THROWS_WITH_AS(_ = j_invalid_utf8.get(), "[json.exception.out_of_range.410] enum value out of range for strict_cards: \"\xEF\xBF\xBD\"", json::out_of_range&); } SECTION("traditional enum")