Skip to content

Commit

Permalink
support variant to_json
Browse files Browse the repository at this point in the history
  • Loading branch information
bbbgan committed Jul 26, 2023
1 parent dd57369 commit 8820159
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 25 deletions.
11 changes: 10 additions & 1 deletion iguana/json_util.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,19 @@ template <typename T>
constexpr inline bool unique_ptr_v =
is_template_instant_of<std::unique_ptr, std::remove_cvref_t<T>>::value;

template <typename T> struct is_variant : std::false_type {};

template <typename... T>
struct is_variant<std::variant<T...>> : std::true_type {};

template <typename T>
constexpr inline bool variant_v = is_variant<std::remove_cvref_t<T>>::value;

template <class T>
constexpr inline bool non_refletable_v =
container_v<T> || c_array_v<T> || tuple_v<T> || optional_v<T> ||
unique_ptr_v<T> || std::is_fundamental_v<std::remove_cvref_t<T>>;
unique_ptr_v<T> || std::is_fundamental_v<std::remove_cvref_t<T>> ||
variant_v<T>;

template <typename T>
constexpr inline bool refletable_v = is_reflection_v<std::remove_cvref_t<T>>;
Expand Down
30 changes: 19 additions & 11 deletions iguana/json_writer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ template <typename Stream, typename T,
std::enable_if_t<refletable_v<T>, int> = 0>
IGUANA_INLINE void to_json(T &&t, Stream &s);

template <typename Stream, typename T>
IGUANA_INLINE void render_json_value(Stream &ss, std::optional<T> &val);

template <typename Stream, typename T,
std::enable_if_t<fixed_array_v<T>, int> = 0>
IGUANA_INLINE void render_json_value(Stream &ss, const T &t);

template <typename Stream, typename T,
std::enable_if_t<sequence_container_v<T>, int> = 0>
IGUANA_INLINE void render_json_value(Stream &ss, const T &v);
Expand All @@ -27,6 +34,9 @@ IGUANA_INLINE void render_json_value(Stream &ss, const T &o);
template <typename Stream, typename T, std::enable_if_t<tuple_v<T>, int> = 0>
IGUANA_INLINE void render_json_value(Stream &ss, const T &v);

template <typename Stream, typename T, std::enable_if_t<variant_v<T>, int> = 0>
IGUANA_INLINE void render_json_value(Stream &s, T &&t);

template <typename Stream, typename InputIt, typename T, typename F>
IGUANA_INLINE void join(Stream &ss, InputIt first, InputIt last, const T &delim,
const F &f) {
Expand Down Expand Up @@ -120,8 +130,7 @@ IGUANA_INLINE void render_array(Stream &ss, const T &v) {
ss.push_back(']');
}

template <typename Stream, typename T,
std::enable_if_t<fixed_array_v<T>, int> = 0>
template <typename Stream, typename T, std::enable_if_t<fixed_array_v<T>, int>>
IGUANA_INLINE void render_json_value(Stream &ss, const T &t) {
if constexpr (std::is_same_v<char, std::remove_reference_t<
decltype(std::declval<T>()[0])>>) {
Expand Down Expand Up @@ -183,7 +192,7 @@ IGUANA_INLINE void render_json_value(Stream &ss, const T &v) {
}
}

template <typename Stream, typename T, std::enable_if_t<tuple_v<T>, int> = 0>
template <typename Stream, typename T, std::enable_if_t<tuple_v<T>, int>>
IGUANA_INLINE void render_json_value(Stream &s, T &&t) {
using U = typename std::decay_t<T>;
s.push_back('[');
Expand All @@ -198,6 +207,11 @@ IGUANA_INLINE void render_json_value(Stream &s, T &&t) {
s.push_back(']');
}

template <typename Stream, typename T, std::enable_if_t<variant_v<T>, int>>
IGUANA_INLINE void render_json_value(Stream &s, T &&t) {
std::visit([&s](auto value) { render_json_value(s, value); }, t);
}

template <typename Stream, typename T, std::enable_if_t<refletable_v<T>, int>>
IGUANA_INLINE void to_json(T &&t, Stream &s) {
s.push_back('{');
Expand All @@ -210,15 +224,9 @@ IGUANA_INLINE void to_json(T &&t, Stream &s) {

write_json_key(s, i, t);
s.push_back(':');

if constexpr (!is_reflection<decltype(v)>::value) {
render_json_value(s, t.*v);
} else {
to_json(t.*v, s);
}

render_json_value(s, t.*v);
if (Idx < Count - 1)
s.push_back(',');
IGUANA_LIKELY { s.push_back(','); }
});
s.push_back('}');
}
Expand Down
36 changes: 23 additions & 13 deletions test/unit_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -619,6 +619,12 @@ TEST_CASE("test the string_view") {
CHECK(*(b.edition) == "invalid number");
}
{
auto validator = [](book_t b) {
CHECK(b.title == "C++ templates");
CHECK(*(b.edition) == "invalid number");
CHECK(b.author[0] == "David Vandevoorde");
CHECK(b.author[1] == "Nicolai M. Josuttis");
};
std::string str = R"({
"title": "C++ templates",
"edition": "invalid number",
Expand All @@ -628,19 +634,23 @@ TEST_CASE("test the string_view") {
]})";
book_t b;
iguana::from_json(b, str);
CHECK(b.title == "C++ templates");
CHECK(*(b.edition) == "invalid number");
CHECK(b.author[0] == "David Vandevoorde");
CHECK(b.author[1] == "Nicolai M. Josuttis");

std::string ss;
iguana::to_json(b, ss);
book_t b1;
iguana::from_json(b1, str);
CHECK(b1.title == "C++ templates");
CHECK(*(b1.edition) == "invalid number");
CHECK(b1.author[0] == "David Vandevoorde");
CHECK(b1.author[1] == "Nicolai M. Josuttis");
validator(b);
{
std::string ss;
iguana::to_json(b, ss);
book_t b1;
iguana::from_json(b1, ss);
validator(b1);
}
{
// test variant
std::variant<int, book_t> vb = b;
std::string ss;
iguana::to_json(vb, ss);
book_t b1;
iguana::from_json(b1, ss);
validator(b1);
}
}
{
std::string str = R"(["tom", 30, 25.8])";
Expand Down

0 comments on commit 8820159

Please sign in to comment.