0

I'm trying to get the cereal serialization library to emit string representations of enums. I'm using the magic_enum library to perform the conversions between the enum and string.

While I have no trouble serializing the given MyStruct to a JSON, while deserializing I get an error.

#include <fmt/core.h>
#include <magic_enum.hpp>
#include <cereal/archives/json.hpp>
#include <fstream>

enum class EnumType : int {
    A, B, C
};

template<class Archive,
        cereal::traits::EnableIf<cereal::traits::is_text_archive<Archive>::value>
        = cereal::traits::sfinae, class T>
std::enable_if_t<std::is_enum_v<T>, std::string> save_minimal(Archive &, const T &h) {
    return std::string(magic_enum::enum_name(h));
}

template<class Archive, cereal::traits::EnableIf<cereal::traits::is_text_archive<Archive>::value>
= cereal::traits::sfinae, class T>
std::enable_if_t<std::is_enum_v<T>, void> load_minimal(Archive const &, T &enumType, std::string const &str) {
    enumType = magic_enum::enum_cast<T>(str).value();
}
struct MyStruct {
    EnumType e;
    std::string s;

    // serialize
    template<class Archive>
    void serialize(Archive &archive) {
        archive(CEREAL_NVP(e), CEREAL_NVP(s));
    }
};

int main() {
    std::string json_file = "s.json";

    // serialize to JSON
    MyStruct s{EnumType::A, "xmcnbx"};
    std::ofstream os(json_file);
    cereal::JSONOutputArchive archive(os); // ok
    archive(s);

    // deserialize from JSON
    MyStruct s2;
    std::ifstream is(json_file);
    cereal::JSONInputArchive archive2(is); // error!
    archive2(s2);
    fmt::print("s2.e = {}, s2.s = {}", magic_enum::enum_name(s2.e), s2.s);
}

s.json (as expected)

{
    "value0": {
        "e": "A",
        "s": "xmcnbx"
    }
}

error message

libc++abi: terminating with uncaught exception of type cereal::RapidJSONException: rapidjson internal assertion failure: IsObject()

Process finished with exit code 134 (interrupted by signal 6: SIGABRT)
marital_weeping
  • 618
  • 5
  • 18
  • 1
    Does this help? https://github.com/Loki-Astari/ThorsSerializer/blob/master/doc/exampleE.md – Martin York Feb 02 '23 at 04:36
  • It does. However, I'll have to introduce another dependency in Thor, which would need a lot of rewriting. Also I'd like to have the serialization library do this for all std::is_enum_v, instead of registering each type separately via a macro. – marital_weeping Feb 02 '23 at 04:45
  • Done. Added magic-enum support. Just wait until brew has approved it. https://github.com/Homebrew/homebrew-core/pull/122394 (don't need to do anything for enum values they will be auto streamed). – Martin York Feb 06 '23 at 08:03

0 Answers0