mirror of
https://github.com/nlohmann/json.git
synced 2026-09-30 22:15:19 +00:00
Fix element path for map/unordered_map JSON_DIAGNOSTICS errors (#5681)
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<std::vector<T>> and similar conversions already do. Fixes #5668. Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
@@ -568,7 +568,7 @@ inline void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allo
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
|
||||
{
|
||||
JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
|
||||
JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &p));
|
||||
}
|
||||
m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
|
||||
}
|
||||
@@ -588,7 +588,7 @@ inline void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Has
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
|
||||
{
|
||||
JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
|
||||
JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &p));
|
||||
}
|
||||
m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
|
||||
}
|
||||
|
||||
@@ -6065,7 +6065,7 @@ inline void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allo
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
|
||||
{
|
||||
JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
|
||||
JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &p));
|
||||
}
|
||||
m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
|
||||
}
|
||||
@@ -6085,7 +6085,7 @@ inline void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Has
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
|
||||
{
|
||||
JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
|
||||
JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &p));
|
||||
}
|
||||
m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
|
||||
}
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
#include <nlohmann/json.hpp>
|
||||
using nlohmann::json;
|
||||
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
|
||||
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<std::map<int, int>>()),
|
||||
"[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<std::unordered_map<int, int>>()),
|
||||
"[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&)
|
||||
|
||||
Reference in New Issue
Block a user