// // json_object_binder.hpp // json // // Created by Sam Jaffe on 4/23/16. // #pragma once namespace json { namespace binder { template class object_binder : public binder_impl { public: object_binder() {} virtual binder_impl* clone() const override { return new object_binder(*this); } template object_binder& operator()(std::string const&k, V T::*ptr, binder_impl const&v) { return (*this)(k, binder(new direct_binder(ptr, binder(v) ))); } object_binder& operator()(std::string const&k, binder const&v) { mapping.emplace(k, v); return *this; } virtual void parse(T& object, char const*& data) const override { const char ch = json::helper::get_next_element(data); if (ch == '{') { parse_object(object, ++data); } else { throw json::malformed_json_exception(std::string("Expected an object type for binding to ") + typeid(T).name()); } } virtual void write(T const& val, std::string & data) const override { data += "{"; for (typename std::map>::const_iterator it = mapping.begin(), end = mapping.end(); it != end; ++it) { data += "\"" + it->first + "\":"; it->second.write(val, data); data += ","; } data.back() = '}'; } void parse_object(T& object, char const*& data) const { std::string key; while (*data && *data != '}') { json::helper::parse_string(key, data); if (json::helper::get_next_element(data) != ':') { throw json::malformed_json_exception(std::string("Expected key:value pair delimited by ':', got '") + *data + "' instead"); } auto it = mapping.find(key); if (it != mapping.end()) { it->second.parse(object, ++data); } else { throw json::malformed_json_exception("Unexpected key " + key); } json::helper::advance_to_boundary('}', data); } if (*data) ++data; else throw json::malformed_json_exception("Reached end of parse string without finding object end"); } template object_binder& operator()(std::string const& s, E T::*p) { return operator()(s, binder(new direct_binder(p))); } private: std::map> mapping; }; } }