c++serializationenumscereal

How to use cereal to serialize enum types?


For example

enum Color {RED, BLUE, YELLOW};

And I want to serialize the type with cereal

Color c = RED;
JSONOutputArchive archive(std::cout);
archive(c);

Output looks like

"value0" : "RED"

or

"value0" : RED

Solution

  • Your desired output is something that no serialization library would be able to perform automatically, because the names you provide for the enum values are known only to the compiler.

    Generally in this type of situation you need to provide code that can translate between a string representation and the numerical value for the enum (e.g., Enum to String C++), or use a library that does this automatically for you.

    Let's assume you have this functionality. You would then need to write ta pair of minimal serialization functions specialized for your enum.

    Here is a fully working example. How you choose to go from enum to string is up to you, I went with two maps because it required no real effort on my part, but you could easily hide all of this behind a macro that would generate all of the required code for you:

    #include <cereal/archives/json.hpp>
    #include <iostream>
    #include <sstream>
    #include <map>
    
    enum Color {RED, BLUE, GREEN};
    enum AnotherEnum {HELLO_WORLD};
    
    std::map<Color, std::string> ColorMapForward = {{RED, "RED"}, {BLUE, "BLUE"}, {GREEN, "GREEN"}};
    std::map<std::string, Color> ColorMapReverse = {{"RED", RED}, {"BLUE", BLUE}, {"GREEN", GREEN}};
    
    std::string Color_tostring( Color c )
    {
      return ColorMapForward[c];
    }
    
    Color Color_fromstring( std::string const & s )
    {
      return ColorMapReverse[s];
    }
    
    namespace cereal
    {
      template <class Archive> inline
      std::string save_minimal( Archive const &, Color const & t )
      {
        return Color_tostring( t );
      }
    
      template <class Archive> inline
      void load_minimal( Archive const &, Color & t, std::string const & value )
      {
        t = Color_fromstring( value );
      }
    }
    
    int main()
    {
      std::stringstream ss;
    
      {
        cereal::JSONOutputArchive ar(ss);
        ar( RED );
        ar( BLUE );
        ar( GREEN );
        ar( HELLO_WORLD ); // uses standard cereal implementation
      }
    
      std::cout << ss.str() << std::endl;
      std::stringstream ss2;
    
      {
        cereal::JSONInputArchive ar(ss);
        cereal::JSONOutputArchive ar2(ss2);
    
        Color r, b, g;
        AnotherEnum a;
    
        ar( r, b, g, a );
        ar2( r, b, g, a );
      }
    
      std::cout << ss2.str() << std::endl;
    }
    

    Gives as output:

    {
        "value0": "RED",
        "value1": "BLUE",
        "value2": "GREEN",
        "value3": 0
    }
    {
        "value0": "RED",
        "value1": "BLUE",
        "value2": "GREEN",
        "value3": 0
    }