Search code examples
c++parsingtemplatesshared-ptrnlohmann-json

How can I `nlohmann::json::get<std::shared_ptr<const T>>`?


I've defined the following serializer stack:

namespace discordpp {
using Snowflake = uint64_t;
}
namespace nlohmann {
template <> struct adl_serializer<discordpp::Snowflake> {
    static void to_json(json &j, const discordpp::Snowflake sf) {
        j = std::to_string(sf);
    }
    
    static void from_json(const json &j, discordpp::Snowflake sf) {
        std::istringstream(j.get<std::string>()) >> sf;
    }
};
template <typename T> struct adl_serializer<std::shared_ptr<T>> {
    static void from_json(json &j, std::shared_ptr<T> &ptr) {
        if (j.is_null()) {
            ptr == nullptr;
        } else {
            ptr = std::make_shared<T>(j.get<T>());
        }
    }
    static void to_json(json &j, const std::shared_ptr<T> &ptr) {
        if (ptr.get()) {
            j = *ptr;
        } else {
            j = nullptr;
        }
    }
};
template <typename T> struct adl_serializer<std::shared_ptr<const T>> {
    static void from_json(json &j, std::shared_ptr<const T> &ptr) {
        if (j.is_null()) {
            ptr == nullptr;
        } else {
            ptr = std::make_shared<const T>(j.get<T>());
        }
    }
    static void to_json(json &j, const std::shared_ptr<const T> &ptr) {
        if (ptr.get()) {
            j = *ptr;
        } else {
            j = nullptr;
        }
    }
};
template <typename T> struct adl_serializer<std::optional<T>> {
    static void to_json(json &j, const std::optional<T> &opt) {
        if (opt.has_value()) {
            j = nullptr;
        } else {
            j = *opt;
        }
    }

    static void from_json(const json &j, std::optional<T> &opt) {
        if (j.is_null()) {
            opt = std::nullopt;
        } else {
            opt = j.get<T>();
        }
    }
};
}

And I'm poking around with things like so:

class MessageIn : protected util::ObjectIn {
  public:
    ...
    opt<sptr<const Snowflake>> guild_id;
    ...
}
void from_json(const json &j, MessageIn *m) {
    ...
    j["guild_id"].get<Snowflake>();
    j["guild_id"].get<const Snowflake>();
    j["guild_id"].get<sptr<const Snowflake>>();
    m->guild_id = j["guild_id"].get<opt<sptr<const Snowflake>>>();
    ...
}

My compiler is throwing an error on the j["guild_id"].get<sptr<const Snowflake>>(); line with error: no matching function for call to ‘nlohmann::basic_json<>::get<discordpp::sptr<const long unsigned int> >() const’. Have I missed something?


Solution

  • The std::shared_ptr<const T> synthesizer is not needed.

    In the from_json methods of both std::shared_ptr sythesizers the json parameter wasn't static.