Skip to content

Commit

Permalink
feat: template spec for custom type
Browse files Browse the repository at this point in the history
  • Loading branch information
MistEO committed Feb 3, 2024
1 parent 149dc20 commit b762d7d
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 32 deletions.
18 changes: 15 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,9 +162,21 @@ struct ThirdPartyStruct
int a = 100;
};
json::value to_json(const ThirdPartyStruct& t) { return t.a; }
bool check_json(const json::value& j, const ThirdPartyStruct&) { return j.is_number(); }
bool from_json(const json::value& j, ThirdPartyStruct& out) { out.a = j.as_integer(); return true; }
namespace json
{
template <>
class serialization<ThirdPartyStruct>
{
public:
json::value to_json(const ThirdPartyStruct& t) { return t.a; }
bool check_json(const json::value& j, const ThirdPartyStruct&) { return j.is_number(); }
bool from_json(const json::value& j, ThirdPartyStruct& out)
{
out.a = j.as_integer();
return true;
}
};
} // namespace json
// 然后可以将其用作 JSON
ThirdPartyStruct third;
Expand Down
18 changes: 15 additions & 3 deletions README_en.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,9 +162,21 @@ struct ThirdPartyStruct
int a = 100;
};
json::value to_json(const ThirdPartyStruct& t) { return t.a; }
bool check_json(const json::value& j, const ThirdPartyStruct&) { return j.is_number(); }
bool from_json(const json::value& j, ThirdPartyStruct& out) { out.a = j.as_integer(); return true; }
namespace json
{
template <>
class serialization<ThirdPartyStruct>
{
public:
json::value to_json(const ThirdPartyStruct& t) { return t.a; }
bool check_json(const json::value& j, const ThirdPartyStruct&) { return j.is_number(); }
bool from_json(const json::value& j, ThirdPartyStruct& out)
{
out.a = j.as_integer();
return true;
}
};
} // namespace json
// then we can use it as json
ThirdPartyStruct third;
Expand Down
2 changes: 1 addition & 1 deletion include/common/array.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class basic_array
template <typename jsonization_t, std::enable_if_t<_utils::has_to_json_in_member<jsonization_t>::value, bool> = true>
basic_array(const jsonization_t& jsonization) : basic_array(jsonization.to_json())
{}
template <typename jsonization_t, std::enable_if_t<_utils::has_to_json_in_global<jsonization_t>::value, bool> = true>
template <typename jsonization_t, std::enable_if_t<_utils::has_to_json_in_templ_spec<jsonization_t>::value, bool> = true>
basic_array(const jsonization_t& jsonization) : basic_array(to_json(jsonization))
{}

Expand Down
2 changes: 1 addition & 1 deletion include/common/object.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class basic_object
template <typename jsonization_t, std::enable_if_t<_utils::has_to_json_in_member<jsonization_t>::value, bool> = true>
basic_object(const jsonization_t& jsonization) : basic_object(jsonization.to_json())
{}
template <typename jsonization_t, std::enable_if_t<_utils::has_to_json_in_global<jsonization_t>::value, bool> = true>
template <typename jsonization_t, std::enable_if_t<_utils::has_to_json_in_templ_spec<jsonization_t>::value, bool> = true>
basic_object(const jsonization_t& jsonization) : basic_object(to_json(jsonization))
{}

Expand Down
30 changes: 23 additions & 7 deletions include/common/utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,18 @@ using warray = basic_array<std::wstring>;
using wobject = basic_object<std::wstring>;
}

namespace json
{
template <typename T, typename string_t = default_string_t>
class serialization
{
public:
// basic_value<string_t> to_json(const T&) const { static_assert(!sizeof(T), "Not Implemented"); }
// bool check_json(const basic_value<string_t>&, const T&) { static_assert(!sizeof(T), "Not Implemented"); }
// bool from_json(const basic_value<string_t>&, T&) { static_assert(!sizeof(T), "Not Implemented"); }
};
}

namespace json::_utils
{
template <typename T>
Expand Down Expand Up @@ -64,10 +76,10 @@ class has_to_json_in_member
};

template <typename T>
class has_to_json_in_global
class has_to_json_in_templ_spec
{
template <typename U>
static auto test(int) -> decltype(to_json(std::declval<U>()), std::true_type());
static auto test(int) -> decltype(std::declval<serialization<U>>().to_json(std::declval<U>()), std::true_type());

template <typename U>
static std::false_type test(...);
Expand All @@ -91,11 +103,13 @@ class has_check_json_in_member
};

template <typename T, typename string_t>
class has_check_json_in_global
class has_check_json_in_templ_spec
{
template <typename U>
static auto test(int)
-> decltype(check_json(std::declval<json::basic_value<string_t>>(), std::declval<U>()), std::true_type());
-> decltype(std::declval<serialization<U>>().check_json(std::declval<json::basic_value<string_t>>(),
std::declval<U>()),
std::true_type());

template <typename U>
static std::false_type test(...);
Expand All @@ -119,11 +133,13 @@ class has_from_json_in_member
};

template <typename T, typename string_t>
class has_from_json_in_global
class has_from_json_in_templ_spec
{
template <typename U>
static auto test(int)
-> decltype(from_json(std::declval<json::basic_value<string_t>>(), std::declval<U&>()), std::true_type());
-> decltype(std::declval<serialization<U>>().from_json(std::declval<json::basic_value<string_t>>(),
std::declval<U&>()),
std::true_type());

template <typename U>
static std::false_type test(...);
Expand Down Expand Up @@ -211,4 +227,4 @@ string_t to_basic_string(any_t&& arg)
static_assert(!sizeof(any_t), "Unsupported type");
}
}
} // namespace json::utils
} // namespace json::_utils
12 changes: 6 additions & 6 deletions include/common/value.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ class basic_value
basic_value(const jsonization_t& jsonization) : basic_value(jsonization.to_json())
{}
template <typename jsonization_t,
std::enable_if_t<_utils::has_to_json_in_global<jsonization_t>::value, bool> = true>
basic_value(const jsonization_t& jsonization) : basic_value(to_json(jsonization))
std::enable_if_t<_utils::has_to_json_in_templ_spec<jsonization_t>::value, bool> = true>
basic_value(const jsonization_t& jsonization) : basic_value(serialization<jsonization_t>().to_json(jsonization))
{}

template <typename value_t, std::enable_if_t<!std::is_convertible_v<value_t, basic_value<string_t>>, bool> = true>
Expand Down Expand Up @@ -230,11 +230,11 @@ class basic_value
return dst;
}
template <typename jsonization_t,
std::enable_if_t<_utils::has_from_json_in_global<jsonization_t, string_t>::value, bool> = true>
std::enable_if_t<_utils::has_from_json_in_templ_spec<jsonization_t, string_t>::value, bool> = true>
explicit operator jsonization_t() const
{
jsonization_t dst;
if (!from_json(*this, dst)) {
if (!serialization<jsonization_t>().from_json(*this, dst)) {
throw exception("Wrong JSON");
}
return dst;
Expand Down Expand Up @@ -389,8 +389,8 @@ inline bool basic_value<string_t>::is() const noexcept
else if constexpr (_utils::has_check_json_in_member<value_t, string_t>::value) {
return value_t().check_json(*this);
}
else if constexpr (_utils::has_check_json_in_global<value_t, string_t>::value) {
return check_json(*this, value_t());
else if constexpr (_utils::has_check_json_in_templ_spec<value_t, string_t>::value) {
return serialization<value_t>().check_json(*this, value_t());
}
else {
static_assert(!sizeof(value_t), "Unsupported type");
Expand Down
24 changes: 13 additions & 11 deletions sample/sample.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,19 +167,21 @@ struct ThirdPartyStruct
int a = 100;
};

json::value to_json(const ThirdPartyStruct& t)
namespace json
{
return t.a;
}
bool check_json(const json::value& j, const ThirdPartyStruct&)
{
return j.is_number();
}
bool from_json(const json::value& j, ThirdPartyStruct& out)
template <>
class serialization<ThirdPartyStruct>
{
out.a = j.as_integer();
return true;
}
public:
json::value to_json(const ThirdPartyStruct& t) { return t.a; }
bool check_json(const json::value& j, const ThirdPartyStruct&) { return j.is_number(); }
bool from_json(const json::value& j, ThirdPartyStruct& out)
{
out.a = j.as_integer();
return true;
}
};
} // namespace json

void third_party_jsonization_1()
{
Expand Down

0 comments on commit b762d7d

Please sign in to comment.