Skip to content

Commit 0efaf89

Browse files
authored
Merge pull request #1089 from theodelrieu/feature/map_conversion
Provide a from_json overload for std::map
2 parents db03d09 + c5e63fd commit 0efaf89

3 files changed

Lines changed: 61 additions & 0 deletions

File tree

include/nlohmann/detail/conversions/from_json.hpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <ciso646> // and, not
66
#include <forward_list> // forward_list
77
#include <iterator> // inserter, front_inserter, end
8+
#include <map> // map
89
#include <string> // string
910
#include <tuple> // tuple, make_tuple
1011
#include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
@@ -277,6 +278,25 @@ void from_json(const BasicJsonType& j, std::tuple<Args...>& t)
277278
from_json_tuple_impl(j, t, index_sequence_for<Args...> {});
278279
}
279280

281+
template <typename BasicJsonType, typename Key, typename Value,
282+
typename = enable_if_t<not std::is_constructible<
283+
typename BasicJsonType::string_t, Key>::value>>
284+
void from_json(const BasicJsonType& j, std::map<Key, Value>& m)
285+
{
286+
if (JSON_UNLIKELY(not j.is_array()))
287+
{
288+
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
289+
}
290+
for (const auto& p : j)
291+
{
292+
if (JSON_UNLIKELY(not p.is_array()))
293+
{
294+
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name())));
295+
}
296+
m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
297+
}
298+
}
299+
280300
struct from_json_fn
281301
{
282302
private:

single_include/nlohmann/json.hpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -909,6 +909,7 @@ inline bool operator<(const value_t lhs, const value_t rhs) noexcept
909909
#include <ciso646> // and, not
910910
#include <forward_list> // forward_list
911911
#include <iterator> // inserter, front_inserter, end
912+
#include <map> // map
912913
#include <string> // string
913914
#include <tuple> // tuple, make_tuple
914915
#include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
@@ -1185,6 +1186,25 @@ void from_json(const BasicJsonType& j, std::tuple<Args...>& t)
11851186
from_json_tuple_impl(j, t, index_sequence_for<Args...> {});
11861187
}
11871188

1189+
template <typename BasicJsonType, typename Key, typename Value,
1190+
typename = enable_if_t<not std::is_constructible<
1191+
typename BasicJsonType::string_t, Key>::value>>
1192+
void from_json(const BasicJsonType& j, std::map<Key, Value>& m)
1193+
{
1194+
if (JSON_UNLIKELY(not j.is_array()))
1195+
{
1196+
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
1197+
}
1198+
for (const auto& p : j)
1199+
{
1200+
if (JSON_UNLIKELY(not p.is_array()))
1201+
{
1202+
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name())));
1203+
}
1204+
m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
1205+
}
1206+
}
1207+
11881208
struct from_json_fn
11891209
{
11901210
private:

test/src/unit-conversions.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1079,6 +1079,26 @@ TEST_CASE("value conversion")
10791079
j5.get<std::unordered_set<std::string>>();
10801080
}
10811081

1082+
SECTION("std::map (array of pairs)")
1083+
{
1084+
std::map<int, int> m{{0, 1}, {1, 2}, {2, 3}};
1085+
json j6 = m;
1086+
1087+
auto m2 = j6.get<std::map<int, int>>();
1088+
CHECK(m == m2);
1089+
1090+
json j7 = {0, 1, 2, 3};
1091+
CHECK_THROWS_AS((j7.get<std::map<int, int>>()), json::type_error&);
1092+
CHECK_THROWS_WITH((j7.get<std::map<int, int>>()), "[json.exception.type_error.302] type must be array, but is number");
1093+
1094+
SECTION("superfluous entries")
1095+
{
1096+
json j8 = {{0, 1, 2}, {1, 2, 3}, {2, 3, 4}};
1097+
m2 = j8.get<std::map<int, int>>();
1098+
CHECK(m == m2);
1099+
}
1100+
}
1101+
10821102
SECTION("exception in case of a non-object type")
10831103
{
10841104
CHECK_THROWS_AS((json().get<std::list<int>>()), json::type_error&);
@@ -1094,6 +1114,7 @@ TEST_CASE("value conversion")
10941114
CHECK_THROWS_WITH((json().get<std::vector<json>>()), "[json.exception.type_error.302] type must be array, but is null");
10951115
CHECK_THROWS_WITH((json().get<std::list<json>>()), "[json.exception.type_error.302] type must be array, but is null");
10961116
CHECK_THROWS_WITH((json().get<std::valarray<int>>()), "[json.exception.type_error.302] type must be array, but is null");
1117+
CHECK_THROWS_WITH((json().get<std::map<int, int>>()), "[json.exception.type_error.302] type must be array, but is null");
10971118
}
10981119
}
10991120
}

0 commit comments

Comments
 (0)