From 5a24b8c2d00e7e08abe218fc8926a7dddc8e9140 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Tue, 29 Sep 2026 23:15:37 +0200 Subject: [PATCH] Fix element path for map/unordered_map JSON_DIAGNOSTICS errors When converting a JSON array to std::map or std::unordered_map with a non-string key, each element must itself be a [key, value] array. If an element is not an array, from_json() threw type_error 302 with the outer array's value (&j) as the exception context, so with JSON_DIAGNOSTICS enabled the message pointed at the whole array instead of the offending element (e.g. "(/outer/m)" instead of "(/outer/m/2)"), even though the message text already described the element's type. Both from_json() overloads now pass the element (&p) as the context, so the reported JSON Pointer matches the type named in the message, the same way std::vector> and similar conversions already do. Fixes #5668. Signed-off-by: Niels Lohmann --- .../nlohmann/detail/conversions/from_json.hpp | 4 +-- single_include/nlohmann/json.hpp | 4 +-- tests/src/unit-diagnostics.cpp | 25 +++++++++++++++++++ 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/include/nlohmann/detail/conversions/from_json.hpp b/include/nlohmann/detail/conversions/from_json.hpp index 11e40f5f4..29505a487 100644 --- a/include/nlohmann/detail/conversions/from_json.hpp +++ b/include/nlohmann/detail/conversions/from_json.hpp @@ -564,7 +564,7 @@ inline void from_json(const BasicJsonType& j, std::map(), p.at(1).template get()); } @@ -584,7 +584,7 @@ inline void from_json(const BasicJsonType& j, std::unordered_map(), p.at(1).template get()); } diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 576498738..23b5e4bec 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -6061,7 +6061,7 @@ inline void from_json(const BasicJsonType& j, std::map(), p.at(1).template get()); } @@ -6081,7 +6081,7 @@ inline void from_json(const BasicJsonType& j, std::unordered_map(), p.at(1).template get()); } diff --git a/tests/src/unit-diagnostics.cpp b/tests/src/unit-diagnostics.cpp index 3ae649e5b..a46ce5746 100644 --- a/tests/src/unit-diagnostics.cpp +++ b/tests/src/unit-diagnostics.cpp @@ -17,6 +17,9 @@ #include using nlohmann::json; +#include +#include + TEST_CASE("Better diagnostics") { SECTION("empty JSON Pointer") @@ -331,6 +334,28 @@ TEST_CASE("Regression tests for extended diagnostics") } } + SECTION("Regression test for issue #5668 - wrong path for std::map/unordered_map with non-string keys") + { + // a map with non-string keys is read from an array of [key, value] arrays; + // element 2 of "m" is not an array, so the path must point at "m/2", not "m" + json j; + j["outer"]["m"] = json::array({json::array({1, 2}), json::array({3, 4}), 5}); + + SECTION("std::map") + { + CHECK_THROWS_WITH_AS((j["outer"]["m"].get>()), + "[json.exception.type_error.302] (/outer/m/2) type must be array, " + "but is number", json::type_error); + } + + SECTION("std::unordered_map") + { + CHECK_THROWS_WITH_AS((j["outer"]["m"].get>()), + "[json.exception.type_error.302] (/outer/m/2) type must be array, " + "but is number", json::type_error); + } + } + SECTION("Regression test - swap(array_t&)/swap(object_t&) must update JSON_DIAGNOSTICS parent pointers") { // swap(array_t&)