I've got the following code (simplified):
namespace nlohmann {
// https://github.com/nlohmann/json/issues/1749#issuecomment-772996219
template <class T>
void to_json(nlohmann::json &j, const std::optional<T> &v) {
if (v.has_value())
j = *v;
else
j = nullptr;
}
template <class T>
void from_json(const nlohmann::json &j, std::optional<T> &v) {
if (j.is_null())
v = std::nullopt;
else
v = j.get<T>(); /* ERROR LOCATION */
}
} // namespace nlohmann
namespace discordpp{
class Component {
public:
Component(const std::optional<std::vector<Component>> &components)
: components(components) {}
std::optional<std::vector<Component>> components;
// (Resolved) NLOHMANN_DEFINE_TYPE_INTRUSIVE(Component, components)
friend void to_json(nlohmann::json &nlohmann_json_j,
const Component &nlohmann_json_t) {
nlohmann_json_j["components"] = nlohmann_json_t.components;
}
friend void from_json(const nlohmann::json &nlohmann_json_j,
Component &nlohmann_json_t) {
nlohmann_json_j.at("components").get_to(nlohmann_json_t.components); /* ERROR LOCATION */
}
};
}// namespace discordpp
Compiling returns the error error: no matching function for call to ‘nlohmann::basic_json<>::get<std::vector<discordpp::Component, std::allocator<discordpp::Component> > >() const’
Is there maybe something I could predeclare to solve this?
Tried setting up an adl_serializer like this, same issue
namespace nlohmann {
template<> struct adl_serializer<discordpp::Component> {
static void to_json(json &nlohmann_json_j, const discordpp::Component &nlohmann_json_t) {
NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(
NLOHMANN_JSON_TO, type, custom_id, disabled, style, label, emoji,
url, options, placeholder, min_values, max_values, components))
}
static void from_json(const json &nlohmann_json_j, discordpp::Component &nlohmann_json_t) {
NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(
NLOHMANN_JSON_FROM, type, custom_id, disabled, style, label, emoji,
url, options, placeholder, min_values, max_values, components))
}
};
} // namespace nlohmann
I changed it to a vector of shared pointers and now I get error: no matching function for call to ‘nlohmann::basic_json<>::get<discordpp::Component>() const’
in the adl_serializer
I wrote to handle it
template <typename T> struct adl_serializer<std::vector<std::shared_ptr<T>>> {
static void to_json(json &j, const std::vector<std::shared_ptr<T>> &v) {
j = json::array();
for (auto t : v) {
j.push_back(*t);
}
}
static void from_json(const json &j, std::vector<std::shared_ptr<T>> &v) {
if (!j.is_array()) {
throw json::type_error::create(317, "j must be an array", j);
}
for (auto t : j) {
v.push_back(std::make_shared<T>(j.get<T>())); /* Error is here */
}
}
};
Mirrored at https://github.com/nlohmann/json/discussions/3047
Edit:
Full source (do a recursive clone): https://github.com/DiscordPP/echo-bot/tree/dev-objects
Failed build: https://github.com/DiscordPP/echo-bot/runs/3799394029?check_suite_focus=true
Edit 2: It's fine when I do std::vector<std::shared_ptr<Component>> components;
, it just doesn't seem to be able handle 2 third party parsers, maybe?
I was doing some thinking on @Niels's answer and I realized that friend void from_json
is taking an already-constructed Component&
but Component
doesn't have a default constructor. I added Component() : components(std::nullopt) {}
and we're off to the races!