add basic test for custom serializer
This commit is contained in:
parent
2bc685f6b4
commit
178441cdfd
2 changed files with 107 additions and 11 deletions
62
src/json.hpp
62
src/json.hpp
|
@ -150,6 +150,38 @@ struct has_mapped_type
|
||||||
std::is_integral<decltype(detect(std::declval<T>()))>::value;
|
std::is_integral<decltype(detect(std::declval<T>()))>::value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <template <typename, typename> class JSONSerializer, typename Json,
|
||||||
|
typename T>
|
||||||
|
struct has_from_json
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
template <typename U, typename = decltype(uncvref_t<U>::from_json(
|
||||||
|
std::declval<Json>(), std::declval<T &>()))>
|
||||||
|
static int detect(U &&);
|
||||||
|
|
||||||
|
static void detect(...);
|
||||||
|
|
||||||
|
public:
|
||||||
|
static constexpr bool value = std::is_integral<decltype(
|
||||||
|
detect(std::declval<JSONSerializer<T, void>>()))>::value;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <template <typename, typename> class JSONSerializer, typename Json,
|
||||||
|
typename T>
|
||||||
|
struct has_to_json
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
template <typename U, typename = decltype(uncvref_t<U>::to_json(
|
||||||
|
std::declval<Json &>(), std::declval<T>()))>
|
||||||
|
static int detect(U &&);
|
||||||
|
|
||||||
|
static void detect(...);
|
||||||
|
|
||||||
|
public:
|
||||||
|
static constexpr bool value = std::is_integral<decltype(
|
||||||
|
detect(std::declval<JSONSerializer<T, void>>()))>::value;
|
||||||
|
};
|
||||||
|
|
||||||
void to_json();
|
void to_json();
|
||||||
void from_json();
|
void from_json();
|
||||||
|
|
||||||
|
@ -1389,7 +1421,8 @@ class basic_json
|
||||||
}
|
}
|
||||||
|
|
||||||
// constructor chosen when JSONSerializer::to_json exists for type T
|
// constructor chosen when JSONSerializer::to_json exists for type T
|
||||||
template <typename T, typename = decltype(JSONSerializer<uncvref_t<T>>::to_json(std::declval<basic_json&>(), std::declval<uncvref_t<T>>()))>
|
template <typename T, typename = typename std::enable_if<detail::has_to_json<
|
||||||
|
JSONSerializer, basic_json, uncvref_t<T>>::value>::type>
|
||||||
explicit basic_json(T &&val)
|
explicit basic_json(T &&val)
|
||||||
{
|
{
|
||||||
JSONSerializer<uncvref_t<T>>::to_json(*this, std::forward<T>(val));
|
JSONSerializer<uncvref_t<T>>::to_json(*this, std::forward<T>(val));
|
||||||
|
@ -3057,19 +3090,26 @@ class basic_json
|
||||||
|
|
||||||
@since version 1.0.0
|
@since version 1.0.0
|
||||||
*/
|
*/
|
||||||
template<typename ValueType, typename std::enable_if<
|
template <typename ValueType,
|
||||||
not std::is_pointer<ValueType>::value, int>::type = 0>
|
typename std::enable_if<
|
||||||
auto get() const -> decltype(this->get_impl(static_cast<ValueType*>(nullptr)))
|
not std::is_pointer<ValueType>::value and
|
||||||
{
|
not detail::has_from_json<JSONSerializer, basic_json,
|
||||||
return get_impl(static_cast<ValueType*>(nullptr));
|
uncvref_t<ValueType>>::value,
|
||||||
|
int>::type = 0>
|
||||||
|
auto get() const
|
||||||
|
-> decltype(this->get_impl(static_cast<ValueType *>(nullptr))) {
|
||||||
|
return get_impl(static_cast<ValueType *>(nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ValueType, typename = decltype(JSONSerializer<uncvref_t<ValueType>>::from_json(std::declval<basic_json>(), std::declval<ValueType&>()))>
|
template <typename ValueType,
|
||||||
auto get() const -> uncvref_t<ValueType>
|
typename = enable_if_t<detail::has_from_json<
|
||||||
{
|
JSONSerializer, basic_json, uncvref_t<ValueType>>::value>>
|
||||||
|
auto get() const -> uncvref_t<ValueType> {
|
||||||
using type = uncvref_t<ValueType>;
|
using type = uncvref_t<ValueType>;
|
||||||
static_assert(std::is_default_constructible<type>::value && std::is_copy_constructible<type>::value,
|
static_assert(std::is_default_constructible<type>::value &&
|
||||||
"user-defined types must be DefaultConstructible and CopyConstructible when used with get");
|
std::is_copy_constructible<type>::value,
|
||||||
|
"user-defined types must be DefaultConstructible and "
|
||||||
|
"CopyConstructible when used with get");
|
||||||
type ret;
|
type ret;
|
||||||
JSONSerializer<type>::from_json(*this, ret);
|
JSONSerializer<type>::from_json(*this, ret);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -379,3 +379,59 @@ TEST_CASE("from_json free function", "[udt]")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// custom serializer, uses adl by default
|
||||||
|
template <typename T, typename = void>
|
||||||
|
struct my_serializer;
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct my_serializer<udt::pod_type>
|
||||||
|
{
|
||||||
|
template <typename Json>
|
||||||
|
static void from_json(Json const& j, udt::pod_type& val)
|
||||||
|
{
|
||||||
|
nlohmann::from_json(j, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Json>
|
||||||
|
static void to_json(Json& j, udt::pod_type const& val)
|
||||||
|
{
|
||||||
|
nlohmann::to_json(j, val);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using my_json = nlohmann::basic_json<std::map, std::vector, std::string, bool,
|
||||||
|
std::int64_t, std::uint64_t, double,
|
||||||
|
std::allocator, my_serializer>;
|
||||||
|
|
||||||
|
namespace udt
|
||||||
|
{
|
||||||
|
void to_json(my_json& j, pod_type const& val)
|
||||||
|
{
|
||||||
|
j = my_json{{"a", val.a}, {"b", val.b}, {"c", val.c}};
|
||||||
|
}
|
||||||
|
|
||||||
|
void from_json(my_json const& j, pod_type& val)
|
||||||
|
{
|
||||||
|
val = {j["a"].get<int>(), j["b"].get<char>(), j["c"].get<short>()};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("custom serializer")
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
SECTION("default use works like default serializer")
|
||||||
|
{
|
||||||
|
udt::pod_type pod{1, 2, 3};
|
||||||
|
auto const j = my_json{pod};
|
||||||
|
|
||||||
|
auto const j2 = json{pod};
|
||||||
|
CHECK(j.dump() == j2.dump());
|
||||||
|
|
||||||
|
auto const pod2 = j.get<udt::pod_type>();
|
||||||
|
auto const pod3 = j2.get<udt::pod_type>();
|
||||||
|
CHECK(pod2 == pod3);
|
||||||
|
CHECK(pod2 == pod);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue