text: #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<std::string, Boxed_Value> 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<Boxed_Value> 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<std::string, Boxed_Value> m = chaiscript::boxed_cast<const std::map<std::string, Boxed_Value> &>(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<Boxed_Value> v = chaiscript::boxed_cast<const std::vector<Boxed_Value> &>(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<double>());
          } else {
            return json::JSON(bn.get_as<std::int64_t>());
          }
        } catch (const chaiscript::detail::exception::bad_any_cast &) {
          // not a number
        }
  
        try {
          return json::JSON(boxed_cast<bool>(t_bv));
        } catch (const chaiscript::exception::bad_boxed_cast &) {
          // not a bool
        }
  
        try {
          return json::JSON(boxed_cast<std::string>(t_bv));
        } catch (const chaiscript::exception::bad_boxed_cast &) {
          // not a string
        }
  
        try {
          const chaiscript::dispatch::Dynamic_Object &o = boxed_cast<const dispatch::Dynamic_Object &>(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
  