#ifndef CHAISCRIPT_SIMPLEJSON_WRAP_HPP #define CHAISCRIPT_SIMPLEJSON_WRAP_HPP #include "json.hpp" namespace chaiscript { class json_wrap { public: static Module &library(Module &m) { m.add(chaiscript::fun([](const std::string &t_str) { return from_json(t_str); }), "from_json"); m.add(chaiscript::fun(&json_wrap::to_json), "to_json"); return m; } private: static Boxed_Value from_json(const json::JSON &t_json) { switch (t_json.JSONType()) { case json::JSON::Class::Null: return Boxed_Value(); case json::JSON::Class::Object: { std::map m; for (const auto &p : t_json.object_range()) { m.insert(std::make_pair(p.first, from_json(p.second))); } return Boxed_Value(m); } case json::JSON::Class::Array: { std::vector vec; for (const auto &p : t_json.array_range()) { vec.emplace_back(from_json(p)); } return Boxed_Value(vec); } case json::JSON::Class::String: return Boxed_Value(t_json.to_string()); case json::JSON::Class::Floating: return Boxed_Value(t_json.to_float()); case json::JSON::Class::Integral: return Boxed_Value(t_json.to_int()); case json::JSON::Class::Boolean: return Boxed_Value(t_json.to_bool()); } throw std::runtime_error("Unknown JSON type"); } static Boxed_Value from_json(const std::string &t_json) { try { return from_json(json::JSON::Load(t_json)); } catch (const std::out_of_range &) { throw std::runtime_error("Unparsed JSON input"); } } static std::string to_json(const Boxed_Value &t_bv) { return to_json_object(t_bv).dump(); } static json::JSON to_json_object(const Boxed_Value &t_bv) { try { const std::map m = chaiscript::boxed_cast &>(t_bv); json::JSON obj(json::JSON::Class::Object); for (const auto &o : m) { obj[o.first] = to_json_object(o.second); } return obj; } catch (const chaiscript::exception::bad_boxed_cast &) { // not a map } try { const std::vector v = chaiscript::boxed_cast &>(t_bv); json::JSON obj(json::JSON::Class::Array); for (size_t i = 0; i < v.size(); ++i) { obj[i] = to_json_object(v[i]); } return obj; } catch (const chaiscript::exception::bad_boxed_cast &) { // not a vector } try { Boxed_Number bn(t_bv); if (Boxed_Number::is_floating_point(t_bv)) { return json::JSON(bn.get_as()); } else { return json::JSON(bn.get_as()); } } catch (const chaiscript::detail::exception::bad_any_cast &) { // not a number } try { return json::JSON(boxed_cast(t_bv)); } catch (const chaiscript::exception::bad_boxed_cast &) { // not a bool } try { return json::JSON(boxed_cast(t_bv)); } catch (const chaiscript::exception::bad_boxed_cast &) { // not a string } try { const chaiscript::dispatch::Dynamic_Object &o = boxed_cast(t_bv); json::JSON obj(json::JSON::Class::Object); for (const auto &attr : o.get_attrs()) { obj[attr.first] = to_json_object(attr.second); } return obj; } catch (const chaiscript::exception::bad_boxed_cast &) { // not a dynamic object } if (t_bv.is_null()) return json::JSON(); // a null value throw std::runtime_error("Unknown object type to convert to JSON"); } }; } // namespace chaiscript #endif