简体   繁体   中英

Cereal/C++ 11 - How to specify optional parameters for de-serialization

I've got class which is de-serialized with standard function:

template<class Archive> // public serialization (normal)
void serialize(Archive & ar)
{
  ar(
    cereal::make_nvp("parameter_1", parameter_1), 
    cereal::make_nvp("parameter_2", parameter_2), 

    cereal::make_nvp("parameter_3", parameter_3), 

    cereal::make_nvp("parameter_4", parameter_4), 

    cereal::make_nvp("parameter_5", parameter_5) ); 
}

But in my case parameter_4 and parameter_5 are optional.

They may or may not be in the input JSON string.

When I'm trying to de-serialize such incomplete JSON with missing some parameters I get Cereal "error" - that cannot find those missing parameters.

Is there any way how to specify that some parameters are optional and in the case that they are not part of JSON default values will be used?

What you might consider doing is adding a 'header' or some basic flags struct that describes what is being passed to/from the archive. eg:

struct Header // can be made private
{
  bool has_parameter_4;
  bool has_parameter_5;
};

template<class Archive> // public serialization (normal)
void serialize(Archive & ar)
{
  // for saving - indicate whether you want the parameters to be saved
  // for loading - these initial values will be overwritten and do not matter
  Header header {should_save_parameter_4(),
                 should_save_parameter_5()}; 

  ar(cereal::make_nvp("header", header), 
     cereal::make_nvp("parameter_1", parameter_1), 
     cereal::make_nvp("parameter_2", parameter_2), 
     cereal::make_nvp("parameter_3", parameter_3));
  if (header.has_parameter_4) 
     ar(cereal::make_nvp("parameter_4", parameter_4));
  if (header.has_parameter_5)
     ar(cereal::make_nvp("parameter_5", parameter_4));
}

The main downside of this method is that you are saving extra information in your JSON/XML/Binary file.

Note: while this question is specific to C++ 11, with the introduction of std::optional in C++ 17 (and cereal's support for std::optional ) you can simply specify the relevant attributes as optional and cereal will take care of the rest. eg:

std::optional<your_type_t> parameter_4 = std::nullopt;

how about:

..
if (exist(parameter_4, parameter_5) {
  ar(
     cereal::make_nvp("parameter_1", parameter_1), 
     cereal::make_nvp("parameter_2", parameter_2), 
     cereal::make_nvp("parameter_3", parameter_3), 
     cereal::make_nvp("parameter_4", parameter_4), 
     cereal::make_nvp("parameter_5", parameter_5) ); 
}
else {
  ar(
     cereal::make_nvp("parameter_1", parameter_1), 
     cereal::make_nvp("parameter_2", parameter_2), 
     cereal::make_nvp("parameter_3", parameter_3) );
}
...

or something similar..

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM