c++jsonserializationcereal

How to serialize a json object without enclosing it in a sub-object using Cereal


Let's say I have a class in C++, like the following:

struct Point {
    int x, y, z;
};

I want to use Cereal to serialize that struct to JSON. So I added a serialize function like this:

struct Point {
    int x, y, z;
    template<class Archive>
    void serialize(Archive& ar) {
        ar(CEREAL_NVP(x),
           CEREAL_NVP(y),
           CEREAL_NVP(z));
    }
};

This works fine when the Point is a member of another object or an element of an array. But if I want to make the Point be the primary object of an entire JSON file, it doesn't work properly. For example, with the following code:

Point p { 1, 2, 3 };
cereal::JSONOutputArchive ar(std::cout);
ar(p);

I get the following output:

{
    "value0": {
        "x": 1,
        "y": 2,
        "z": 3
    }
}

I'd like to remove the "value0" key and elevate the object to occupy the entire file, like this:

{
    "x": 1,
    "y": 2,
    "z": 3
}

The only way I can seem to do that, is to basically re-implement the serialization function, manually adding the key names.

Point p {1, 2, 3};
cereal::JSONOutputArchive ar(std::cout);
ar(cereal::make_nvp("x", p.x),
   cereal::make_nvp("y", p.y),
   cereal::make_nvp("z", p.z));

Is there any way to do it utilizing the serialize function that I already implemented for the class?


Solution

  • Okay, figured it out. Pretty simple, just needed to call the serialize function directly from the object, passing the archive, instead of passing the object to the archive.

    Point p {1, 2, 3};
    cereal::JSONOutputArchive ar(std::cout);
    p.serialize(ar);