Closed 0xBYTESHIFT closed 3 years ago
I tried different approach, but the results are not much better:
#include <iostream>
#include <daw/json/daw_json_link.h>
#include <magic_enum.hpp>
namespace api
{
enum class code : int
{
OK = 0,
ERROR
};
struct request
{
std::string type = "request";
code c;
};
constexpr auto to_string(api::code c)
{
return magic_enum::enum_name(c);
}
constexpr auto from_string(daw::tag_t<api::code>, std::string_view sv) -> api::code
{
auto c = magic_enum::enum_cast<api::code>(sv);
if (c.has_value())
{
return c.value();
}
throw std::runtime_error("unknown api::code");
}
};
namespace daw::json
{
template <>
struct json_data_contract<api::request>
{
static constexpr char const name_type[] = "type";
static constexpr char const name_code[] = "code";
using type = json_member_list<
json_string<name_type>,
json_string<name_code, json_custom<no_name, api::code>>>;
static inline auto to_json_data(const api::request &value)
{
return std::forward_as_tuple(
value.type,
value.c);
}
};
} // namespace daw::json
int main(int, char **)
{
auto data = "{ \"type\":\"request\", \"code\":0 }";
auto req = daw::json::from_json<api::request>(data);
std::cout << daw::json::to_json(req) << "\n";
}
Ok, I managed to do it with json_custom and universal enum adapter like that:
#include <iostream>
#include <daw/json/daw_json_link.h>
#include <magic_enum.hpp>
namespace api
{
struct request
{
enum class code : int
{
OK = 0,
ERROR
};
std::string type = "request";
code c;
};
};
template <class T>
struct CodeConverter
{
auto operator()(std::string_view sv) const -> T
{
auto c = magic_enum::enum_cast<T>(sv);
if (c.has_value())
{
return c.value();
}
throw std::runtime_error("unknown enum");
}
auto operator()(T c) const -> std::string_view
{
return magic_enum::enum_name(c);
}
};
namespace daw::json
{
template <>
struct json_data_contract<api::request>
{
static constexpr char const name_type[] = "type";
static constexpr char const name_code[] = "code";
using code_t = api::request::code;
using type = json_member_list<
json_string<name_type>,
json_custom<name_code, code_t, CodeConverter<code_t>, CodeConverter<code_t>>>;
static inline auto to_json_data(const api::request &value)
{
return std::forward_as_tuple(
value.type,
value.c);
}
};
} // namespace daw::json
int main(int, char **)
{
auto data = "{ \"type\":\"request\", \"code\":\"OK\" }";
auto req = daw::json::from_json<api::request>(data);
std::cout << daw::json::to_json(req) << "\n";
}
First, for enum's you should specify the type in the mapping, json_number<name_code, api::request::code>
Also keep in mind is you are mapping the JSON members needed to construct your class, but are trying to construct a request with 2 elements. The error can be improved here and will be in future versions.
Because the type member is a static
, it plays no part in requests
construction.
Regarding encoding enum's : https://github.com/beached/daw_json_link/blob/release/cookbook/enums.md
Also, I suspect you will be doing a variant like pattern here, so this may come in handy too https://github.com/beached/daw_json_link/blob/release/cookbook/variant.md
There was a bug in enum classes with signed underlying types(that should have been default parsed but I generally have unsigned ones) that was missed in test(now tested) It will be in release once https://github.com/beached/daw_json_link/pull/229 is merged
Sorry, I had a Sunday morning lack of coffee mishap. The PR is https://github.com/beached/daw_json_link/pull/230
As of https://github.com/beached/daw_json_link/releases/tag/v2.9.3 the fixes are in release
Here's the code:
Why can't I use enums with json_number? Making
enum class something : int{}
doesn't help either.It produces compile errors like that:
Errors
``` FAILED: CMakeFiles/example.dir/main.cpp.o /bin/clang++-11 -I_deps/daw_json_link-src/include -I_deps/daw_utf_range-src/include -isystem _deps/daw_header_libraries-src/include -g -std=gnu++17 -MD -MT CMakeFiles/example.dir/main.cpp.o -MF CMakeFiles/example.dir/main.cpp.o.d -o CMakeFiles/example.dir/main.cpp.o -c ../main.cpp In file included from ../main.cpp:2: In file included from _deps/daw_json_link-src/include/daw/json/daw_json_link.h:10: In file included from _deps/daw_json_link-src/include/daw/json/daw_from_json.h:11: In file included from _deps/daw_json_link-src/include/daw/json/daw_from_json_fwd.h:11: In file included from _deps/daw_json_link-src/include/daw/json/impl/daw_json_link_types_fwd.h:12: In file included from _deps/daw_json_link-src/include/daw/json/impl/daw_json_link_impl.h:12: In file included from _deps/daw_json_link-src/include/daw/json/impl/daw_json_assert.h:11: In file included from _deps/daw_json_link-src/include/daw/json/daw_json_exception.h:12: In file included from _deps/daw_header_libraries-src/include/daw/daw_string_view.h:11: In file included from _deps/daw_header_libraries-src/include/daw/iterator/../daw_algorithm.h:11: In file included from _deps/daw_header_libraries-src/include/daw/iterator/../cpp_17.h:19: /bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/tuple:1727:14: error: no matching function for call to '__invoke' return std::__invoke(std::forward<_Fn>(__f), ^~~~~~~~~~~~~ /bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/tuple:1738:19: note: in instantiation of function template specialization 'std::__apply_impl