2

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?

Aido
  • 1,524
  • 3
  • 18
  • 41
  • for some reason I get similar errors, even though methods are statics. Any chance you can post/edit with "final" adl_serializer code that worked for you ? – IdanB Aug 22 '21 at 16:15
  • @IdanB I moved away from doing it this way, but I did end up using this: https://github.com/nlohmann/json/issues/1749#issuecomment-772996219 – Aido Aug 30 '21 at 15:30
  • @IdanB Oh yeah, I think I started running into issues where Nlohmann's JSON made every integer into a `std::string` I setteled on a combination of this method: https://github.com/DiscordPP/discordpp/blob/f301d149fd0c7b65050a0735eba08b66a7f31a47/discordpp/util.hh#L43-L50 And manually converting it back and forth from a string: https://github.com/search?p=2&q=org%3ADiscordPP+snowflake&type=Code – Aido Aug 30 '21 at 15:34

1 Answers1

1

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.

Sreeraj Chundayil
  • 5,548
  • 3
  • 29
  • 68
Aido
  • 1,524
  • 3
  • 18
  • 41