// Copyright Louis Dionne 2013-2017 // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace hana = boost::hana; struct Car { BOOST_HANA_DEFINE_STRUCT(Car, (std::string, brand), (std::string, model) ); }; struct Person { BOOST_HANA_DEFINE_STRUCT(Person, (std::string, name), (std::string, last_name), (int, age) ); }; template std::enable_if_t::value, T> from_json(std::istream& in) { T result; in >> result; return result; } template std::enable_if_t::value, T> from_json(std::istream& in) { char quote; in >> quote; T result; char c; while (in.get(c) && c != '"') { result += c; } return result; } template std::enable_if_t::value, T> from_json(std::istream& in) { T result; char brace; in >> brace; // CAREFUL: This only works if the input JSON contains the fields in the // same order as the struct declares them. hana::for_each(hana::keys(result), [&](auto key) { in.ignore(std::numeric_limits::max(), ':'); auto& member = hana::at_key(result, key); using Member = std::remove_reference_t; member = from_json(in); }); in >> brace; return result; } template std::enable_if_t::value, Xs> from_json(std::istream& in) { Xs result; char bracket; in >> bracket; hana::length(result).times.with_index([&](auto i) { if (i != 0u) { char comma; in >> comma; } auto& element = hana::at(result, i); using Element = std::remove_reference_t; element = from_json(in); }); in >> bracket; return result; } int main() { std::istringstream json(R"EOS( [ { "name": "John", "last_name": "Doe", "age": 30 }, { "brand": "BMW", "model": "Z3" }, { "brand": "Audi", "model": "A4" } ] )EOS"); auto actual = from_json>(json); auto expected = hana::make_tuple(Person{"John", "Doe", 30}, Car{"BMW", "Z3"}, Car{"Audi", "A4"}); BOOST_HANA_RUNTIME_CHECK(actual == expected); }