summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/hana/example/misc/from_json.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/boost/libs/hana/example/misc/from_json.cpp')
-rw-r--r--src/boost/libs/hana/example/misc/from_json.cpp129
1 files changed, 129 insertions, 0 deletions
diff --git a/src/boost/libs/hana/example/misc/from_json.cpp b/src/boost/libs/hana/example/misc/from_json.cpp
new file mode 100644
index 00000000..a28cac1e
--- /dev/null
+++ b/src/boost/libs/hana/example/misc/from_json.cpp
@@ -0,0 +1,129 @@
+// 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 <boost/hana/assert.hpp>
+#include <boost/hana/at.hpp>
+#include <boost/hana/at_key.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/concept/struct.hpp>
+#include <boost/hana/define_struct.hpp>
+#include <boost/hana/for_each.hpp>
+#include <boost/hana/keys.hpp>
+#include <boost/hana/length.hpp>
+#include <boost/hana/not_equal.hpp>
+#include <boost/hana/tuple.hpp>
+
+#include <iostream>
+#include <limits>
+#include <sstream>
+#include <string>
+#include <type_traits>
+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 <typename T>
+ std::enable_if_t<std::is_same<T, int>::value,
+T> from_json(std::istream& in) {
+ T result;
+ in >> result;
+ return result;
+}
+
+template <typename T>
+ std::enable_if_t<std::is_same<T, std::string>::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 <typename T>
+ std::enable_if_t<hana::Struct<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<std::streamsize>::max(), ':');
+ auto& member = hana::at_key(result, key);
+ using Member = std::remove_reference_t<decltype(member)>;
+ member = from_json<Member>(in);
+ });
+ in >> brace;
+ return result;
+}
+
+template <typename Xs>
+ std::enable_if_t<hana::Sequence<Xs>::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<decltype(element)>;
+ element = from_json<Element>(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<hana::tuple<Person, Car, Car>>(json);
+
+ auto expected = hana::make_tuple(Person{"John", "Doe", 30},
+ Car{"BMW", "Z3"},
+ Car{"Audi", "A4"});
+
+ BOOST_HANA_RUNTIME_CHECK(actual == expected);
+}