Skip to content

Create a [key:member_pointer] map to ease parsing custom types #471

Description

@fnc12

Once from_json and to_json functions overloading appeared in the lib it became easy to build and serialize custom classes from and to json. But it can be more easy if lib provide ability to create a map for each type with json keys strings and member pointers as values.

For example right now one have to write a code like this

Regions.h

#include <string>
#include <vector>
#include <json/json.hpp>

#include "City.hpp"

namespace DataModel {
    
    struct Region {
        std::string name;
        std::vector<City> cities;
    };
    
    using nlohmann::json;
    
    void to_json(json &j, const Region &o);
    
    void from_json(const json &j, Region &o);
}

Region.cpp

#include "Region.hpp"

namespace Keys {
    const std::string name = "name";
    const std::string cities = "cities";
}

void DataModel::to_json(json &j, const Region &o) {
    using namespace Keys;
    j = {
        { name, o.name },
        { cities, o.cities },
    };
}

void DataModel::from_json(const json &j, Region &o) {
    using namespace Keys;
    o.name = j[name];
    o.cities = j[cities].get<decltype(o.cities)>();
}

Now keys are stored in datamodel class implementation file. It's ok but it can be implemented even shorter and more comfortable if lib could store an std::map<std::string, F T::*> for T class (Region in the example above). Of course one cannot create such a map in C++ cause value may have different types. But this kind of mapping can be implemented with variadic templates just like sqlite_orm works (look at make_column function). To implement this functionality developer can create template specialization like this:

Region.hpp

#include <string>
#include <vector>
#include <json/json.hpp>

#include "City.hpp"

namespace DataModel {
    
    struct Region {
        std::string name;
        std::vector<City> cities;
    };
    
    using nlohmann::json;
    
    template<>
    struct key_value_mapper<Region> {
        auto operator()() const {
            return make_mapper(make_mapping("name", &Region::name), make_mapping("cities", &Region::cities));
        }
    };
}

City is omitted in the example but it also has from_json and to_json overriden and has the only field std::string name.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions