USCiLab / cereal

A C++11 library for serialization
BSD 3-Clause "New" or "Revised" License
4.25k stars 767 forks source link

How do I remove excess layers #820

Open zgmslm opened 8 months ago

zgmslm commented 8 months ago

When I use cereal:

#include <iostream>  
#include <sstream>  
#include <cereal/types/string.hpp>  
#include <cereal/archives/json.hpp>  

struct person
{
    std::string name;
    int age;

    template <class Archive>
    void serialize(Archive & archive)
    {
        archive(CEREAL_NVP(name), CEREAL_NVP(age));
    }
};

int main()
{
    person p = { "Alice", 30 };

    std::stringstream ss;
    {
        cereal::JSONOutputArchive archive(ss);
        archive(p);
    }

    std::string json_string = ss.str();
    std::cout << "Serialized JSON: \n" << json_string << std::endl;

    return 0;
}

I expect to serialize to the string: { "name": "Alice", "age": 30 }

But the serialized string is:

{
    "value0": {
        "name": "Alice",
        "age": 30
    }
}

cereal adds an additional layer to the top object, How do I use cereal to generate json with no additional layers?

dimateos commented 6 months ago

In general, I think you cant.

Cereal is expecting more than a single "Person" to be serialized, so it writes an outer json where it puts each of the serialized objects.

You can name each object using CEREAL_NVP direclty at archive(p); to overwrite the default keyname "value0". Or for this toy example you could get no additional layers by manually serializing each field from outside: archive(cereal::make_nvp("name", p.name), cereal::make_nvp("age", p.age));... but not very escalable.

I believe Cereal is more for serializing the state of your app, preferably in binary archives but you have human readable for simple cases / debugging purposes. Is not really suited for loading/writing config files.

hatrd commented 2 months ago

try p.serialize(archive);