Stefan Densow
Stefan Densow

Reputation: 143

C++/Cereal: Exception while deserializing from JSON to own class

I'm trying to load parameters from a JSON file into my own parameter class using cereal (v1.12) on VS2013.

Compilation and loading into a POD works fine, but loading into my own class throws cereal::RapidJSONException.

Here is my code:

#include <iostream>
#include "cereal/archives/json.hpp"

struct CMyStruct {
    CMyStruct(int f_value) : m_value(f_value) {}
    int   m_value;
};

template<class Archive> void load(Archive& ar, CMyStruct& parameter) {
    int input;
    ar(input);
    parameter.m_value = input;
};

void test_cereal() {    
    int l_scalar_i(42);
    CMyStruct l_scalar(42);

    std::ifstream l_jsonFile("example_minimal.json");
    cereal::JSONInputArchive l_ar(l_jsonFile);

    l_ar( cereal::make_nvp("scalar", l_scalar_i) ); // WORKS
    l_ar( cereal::make_nvp("scalar", l_scalar) );   // throws cereal::RapidJSONException

    return;
}

The JSON file:

{
    "bool": false,
    "scalar": 3
}

Following the call stack shows that document.h:244 inside RapidJSON throws the exception:

ConstMemberIterator MemberEnd() const
{ RAPIDJSON_ASSERT(IsObject()); return data_.o.members + data_.o.size; }

However, I have no idea what to make of it. How can I make my code work?

Thanks a lot!

UPDATE WITH SOLUTION:

As written by ChrisBFX, it is necessary to implement load_minimal/save_minimal in order to deserialize an C++ object to a JSON scalar.

load/save on the other hand serializes a C++ object from/to a JSON object.

For my code, the load() function has to be removed and replaced by this:

template<class Archive>
int save_minimal(const Archive& ar,
    const CMyStruct& parameter)
{
    return parameter.m_value;
};

template<class Archive>
void load_minimal(const Archive& ar,
    CMyStruct& parameter,
    const int & value_i)
{
    parameter.m_value = value_i;
};

Now it works like a charm! :-)

Upvotes: 2

Views: 2225

Answers (1)

ChrisBFX
ChrisBFX

Reputation: 71

Your CMStruct is not a scalar but an object. So cereal expects

{
    "bool": false,
    "scalar": {
        "value": 3
    }
}

If you want to serialize your struct as a scalar you have to provide a minimal_load function for it. See http://uscilab.github.io/cereal/serialization_functions.html "minimal split serialization".

Upvotes: 2

Related Questions