Skip to content

magic json serialization #24

@omartijn

Description

@omartijn

I recently discovered Boost.PFR, which allows a form of reflection on simple aggregates. Reading the field names is, unfortunately, only supported in c++20 (so we couldn't add direct support for it inside json_dto), but I think it's useful enough that it warrants an example, and maybe a mention in the main README. Take the following code:

#include <boost/pfr.hpp>
#include <iostream>
#include <json_dto/pub.hpp>

struct bla {
    int x;
    float y;
    std::string z;
};

template <typename wrapped>
class aggregate {
   public:
    aggregate(wrapped& data) : data{data} {}

    template <typename io_type>
    void json_io(io_type& io) {
        json_io(io,
                std::make_index_sequence<boost::pfr::tuple_size_v<wrapped>>());
    }

   private:
    template <typename io_type, std::size_t... i>
    void json_io(io_type& io, std::index_sequence<i...>) {
        ((io &
          json_dto::mandatory(
              rapidjson::StringRef(boost::pfr::get_name<i, wrapped>().data(),
                                   boost::pfr::get_name<i, wrapped>().size()),
              boost::pfr::get<i>(data))),
         ...);
    }

    wrapped& data;
};

int main() {
    bla x{1, 2.5f, "greetings"};

    auto result = json_dto::to_json(aggregate{x});
    std::cout << result << std::endl;

    bla y{};
    aggregate a{y};
    std::string input{"{\"x\":1,\"y\":2.5,\"z\":\"greetings\"}"};
    json_dto::from_json(input, a);

    assert(x.x == y.x);
    assert(x.y == y.y);
    assert(x.z == y.z);
}

This example highlights (de)serializing structs without manually binding the fields! Simply add a field and it's automatically (de)serialized.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions