add std::pair<CompatibleStringType, T> support

This commit is contained in:
Théo DELRIEU 2017-06-06 13:44:35 +02:00
parent 1a9d76679a
commit 85de93ba93
No known key found for this signature in database
GPG key ID: C64D5E244E08ADC6
2 changed files with 59 additions and 3 deletions

View file

@ -285,7 +285,7 @@ class invalid_iterator : public exception
Exceptions have ids 3xx. Exceptions have ids 3xx.
name / id | example massage | description name / id | example message | description
----------------------------- | --------------- | ------------------------- ----------------------------- | --------------- | -------------------------
json.exception.type_error.301 | cannot create object from initializer list | To create an object from an initializer list, the initializer list must consist only of a list of pairs whose first element is a string. When this constraint is violated, an array is created instead. json.exception.type_error.301 | cannot create object from initializer list | To create an object from an initializer list, the initializer list must consist only of a list of pairs whose first element is a string. When this constraint is violated, an array is created instead.
json.exception.type_error.302 | type must be object, but is array | During implicit or explicit value conversion, the JSON type must be compatible to the target type. For instance, a JSON string can only be converted into string types, but not into numbers or boolean types. json.exception.type_error.302 | type must be object, but is array | During implicit or explicit value conversion, the JSON type must be compatible to the target type. For instance, a JSON string can only be converted into string types, but not into numbers or boolean types.
@ -324,7 +324,7 @@ class type_error : public exception
Exceptions have ids 4xx. Exceptions have ids 4xx.
name / id | example massage | description name / id | example message | description
------------------------------- | --------------- | ------------------------- ------------------------------- | --------------- | -------------------------
json.exception.out_of_range.401 | array index 3 is out of range | The provided array index @a i is larger than @a size-1. json.exception.out_of_range.401 | array index 3 is out of range | The provided array index @a i is larger than @a size-1.
json.exception.out_of_range.402 | array index '-' (3) is out of range | The special array index `-` in a JSON Pointer never describes a valid element of the array, but the index past the end. That is, it can only be used to add elements at this position, but not to read it. json.exception.out_of_range.402 | array index '-' (3) is out of range | The special array index `-` in a JSON Pointer never describes a valid element of the array, but the index past the end. That is, it can only be used to add elements at this position, but not to read it.
@ -355,9 +355,10 @@ class out_of_range : public exception
Exceptions have ids 5xx. Exceptions have ids 5xx.
name / id | example massage | description name / id | example message | description
------------------------------ | --------------- | ------------------------- ------------------------------ | --------------- | -------------------------
json.exception.other_error.501 | unsuccessful: {"op":"test","path":"/baz", "value":"bar"} | A JSON Patch operation 'test' failed. The unsuccessful operation is also printed. json.exception.other_error.501 | unsuccessful: {"op":"test","path":"/baz", "value":"bar"} | A JSON Patch operation 'test' failed. The unsuccessful operation is also printed.
json.exception.other_error.502 | invalid object size for conversion | Some conversions to user-defined types impose constraints on the object size (e.g. std::pair)
@since version 3.0.0 @since version 3.0.0
*/ */
@ -865,6 +866,14 @@ void to_json(BasicJsonType& j, T (&arr)[N])
external_constructor<value_t::array>::construct(j, arr); external_constructor<value_t::array>::construct(j, arr);
} }
template <typename BasicJsonType, typename CompatibleString, typename T,
enable_if_t<std::is_constructible<typename BasicJsonType::string_t,
CompatibleString>::value, int> = 0>
void to_json(BasicJsonType& j, std::pair<CompatibleString, T> const& p)
{
j[p.first] = p.second;
}
/////////////// ///////////////
// from_json // // from_json //
/////////////// ///////////////
@ -1086,6 +1095,27 @@ void from_json(const BasicJsonType& j, ArithmeticType& val)
} }
} }
template <typename BasicJsonType, typename CompatibleString, typename T,
enable_if_t<std::is_constructible<typename BasicJsonType::string_t,
CompatibleString>::value, int> = 0>
void from_json(const BasicJsonType& j, std::pair<CompatibleString, T>& p)
{
if (not j.is_object())
{
JSON_THROW(type_error::create(302, "type must be object, but is " + j.type_name()));
}
auto const inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
auto const size = inner_object->size();
if (size != 1)
{
JSON_THROW(other_error::create(502, "conversion to std::pair requires the object to have exactly one field, but it has " + std::to_string(size)));
}
auto const& obj = *inner_object->begin();
// cannot use *inner_object, need to convert both members
p = std::make_pair(obj.first, obj.second.template get<T>());
}
struct to_json_fn struct to_json_fn
{ {
private: private:

View file

@ -156,6 +156,20 @@ TEST_CASE("constructors")
CHECK(j == j_reference); CHECK(j == j_reference);
} }
SECTION("std::pair<CompatibleString, T>")
{
std::pair<std::string, std::string> p{"first", "second"};
json j(p);
CHECK((j.get<decltype(p)>() == p));
std::pair<std::string, int> p2{"first", 1};
// use char const*
json j2(std::make_pair("first", 1));
CHECK((j2.get<decltype(p2)>() == p2));
}
SECTION("std::map<const char*, json>") SECTION("std::map<const char*, json>")
{ {
std::map<const char*, json> o {{"a", json(1)}, {"b", json(1u)}, {"c", json(2.2)}, {"d", json(false)}, {"e", json("string")}, {"f", json()}}; std::map<const char*, json> o {{"a", json(1)}, {"b", json(1u)}, {"c", json(2.2)}, {"d", json(false)}, {"e", json("string")}, {"f", json()}};
@ -164,6 +178,7 @@ TEST_CASE("constructors")
CHECK(j == j_reference); CHECK(j == j_reference);
} }
SECTION("std::multimap<json::string_t, json>") SECTION("std::multimap<json::string_t, json>")
{ {
std::multimap<json::string_t, json> o {{"a", json(1)}, {"b", json(1u)}, {"c", json(2.2)}, {"d", json(false)}, {"e", json("string")}, {"f", json()}}; std::multimap<json::string_t, json> o {{"a", json(1)}, {"b", json(1u)}, {"c", json(2.2)}, {"d", json(false)}, {"e", json("string")}, {"f", json()}};
@ -954,6 +969,17 @@ TEST_CASE("constructors")
"[json.exception.type_error.301] cannot create object from initializer list"); "[json.exception.type_error.301] cannot create object from initializer list");
} }
SECTION("std::pair<CompatibleString, T> with error")
{
json j{{"too", "much"}, {"string", "fields"}};
CHECK_THROWS_AS((j.get<std::pair<std::string, std::string>>()), json::other_error);
CHECK_THROWS_WITH((j.get<std::pair<std::string, std::string>>()),
"[json.exception.other_error.502] conversion "
"to std::pair requires the object to have "
"exactly one field, but it has 2");
}
SECTION("empty array") SECTION("empty array")
{ {
json j = json::array(); json j = json::array();