Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allow json to have missing NVP #214

Closed
wants to merge 1 commit into from

Conversation

asa
Copy link
Contributor

@asa asa commented Nov 1, 2024

Using cereal allows common structs to be serdes using json.
Missing fields in the json cause an exception on load. This slows down iteration in use-cases where the structs are changing versions. This branch silently falls back to a default constructed field if it is not able to be loaded.

This silent healing may not be appreciated in some use-cases. Perhaps all this should be hidden behind a config?

@arximboldi
Copy link
Owner

I don't think that approach is safe, as it can hide other legitimate exceptions. I use this code in other projects:

#pragma once
#pragma once

#include <cereal/cereal.hpp>
#include <cereal/details/traits.hpp>

namespace cereal {

template <typename Archive, typename T>
bool serialize_optional_nvp(Archive& ar, const char* name, T&& value)
{
    constexpr bool isTextArchive = traits::is_text_archive<Archive>::value;
    constexpr bool isInputArchive =
        std::is_base_of_v<InputArchive<Archive>, Archive>;

    // Do check for node here, if not available then bail!
    if constexpr (isTextArchive && isInputArchive) {
        if (!ar.hasName(name))
            return false;
    }

    ar(make_nvp(name, std::forward<T>(value)));

    return true;
}

} // namespace cereal

#define CEREAL_OPTIONAL_NVP(ar, T) ::cereal::make_optional_nvp(ar, #T, T)

Even though I have this code to serialize Hana structs, including optional camelCase conversion...

#pragma once

#include <bnz/util/cereal/optional_nvp.hpp>

#include <cereal/cereal.hpp>

#include <boost/hana/at_key.hpp>
#include <boost/hana/concept/struct.hpp>
#include <boost/hana/for_each.hpp>
#include <boost/hana/keys.hpp>

#include <boost/core/demangle.hpp>

namespace bnz {
namespace util {

// Converts snake_case, SCREAMING_CASE, and kebap-case to camelCase
inline std::string to_camel_case(std::string str)
{
    auto in       = str.begin();
    auto out      = in;
    auto last     = str.end();
    auto new_word = false;
    for (; in != last; ++in) {
        auto c = *in;
        if (std::isdigit(c)) {
            *out++ = c;
        } else if (!std::isalpha(c)) {
            new_word = true;
        } else if (new_word) {
            *out++   = std::toupper(*in);
            new_word = false;
        } else {
            *out++ = std::tolower(*in);
        }
    }
    str.resize(out - str.begin());
    return str;
}

} // namespace util
} // namespace bnz

namespace cereal {

template <typename T, typename Enable = void>
struct serialize_camel_case : std::false_type
{};

template <typename T>
struct serialize_camel_case<T, std::enable_if_t<T::serialize_camel_case>>
    : std::true_type
{};

template <typename Archive, typename T>
std::enable_if_t<boost::hana::Struct<T>::value &&
                 !serialize_camel_case<T>::value>
CEREAL_SERIALIZE_FUNCTION_NAME(Archive& ar, T& v)
{
    boost::hana::for_each(boost::hana::keys(v), [&](auto&& k) {
        serialize_optional_nvp(ar, k.c_str(), boost::hana::at_key(v, k));
    });
}

template <typename Archive, typename T>
std::enable_if_t<boost::hana::Struct<T>::value &&
                 serialize_camel_case<T>::value>
CEREAL_SERIALIZE_FUNCTION_NAME(Archive& ar, T& v)
{
    boost::hana::for_each(boost::hana::keys(v), [&](auto&& k) {
        serialize_optional_nvp(
            ar, bnz::util::to_camel_case(k.c_str()), boost::hana::at_key(v, k));
    });
}

} // namespace cereal

@arximboldi arximboldi closed this Nov 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants