json_object_binder.hpp 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. //
  2. // json_object_binder.hpp
  3. // json
  4. //
  5. // Created by Sam Jaffe on 4/23/16.
  6. //
  7. #pragma once
  8. namespace json { namespace binder {
  9. template <typename T>
  10. class object_binder : public binder_impl<T> {
  11. public:
  12. object_binder() {}
  13. virtual binder_impl<T>* clone() const override { return new object_binder(*this); }
  14. template <typename V>
  15. object_binder& operator()(std::string const&k, V T::*ptr, binder_impl<V> const&v) {
  16. return (*this)(k, binder<T>(new direct_binder<T, V>(ptr, binder<V>(v) )));
  17. }
  18. object_binder& operator()(std::string const&k, binder<T> const&v) {
  19. mapping.emplace(k, v);
  20. return *this;
  21. }
  22. virtual void parse(T& object, char const*& data) const override {
  23. const char ch = json::helper::get_next_element(data);
  24. if (ch == '{') {
  25. parse_object(object, ++data);
  26. } else {
  27. throw json::malformed_json_exception(std::string("Expected an object type for binding to ") + typeid(T).name());
  28. }
  29. }
  30. virtual void write(T const& val, std::string & data) const override {
  31. data += "{";
  32. for (typename std::map<std::string, binder<T>>::const_iterator it = mapping.begin(),
  33. end = mapping.end(); it != end; ++it) {
  34. data += "\"" + it->first + "\":";
  35. it->second.write(val, data);
  36. data += ",";
  37. }
  38. data.back() = '}';
  39. }
  40. void parse_object(T& object, char const*& data) const {
  41. std::string key;
  42. while (*data && *data != '}') {
  43. json::helper::parse_string(key, data);
  44. if (json::helper::get_next_element(data) != ':') {
  45. throw json::malformed_json_exception(std::string("Expected key:value pair delimited by ':', got '") + *data + "' instead");
  46. }
  47. auto it = mapping.find(key);
  48. if (it != mapping.end()) {
  49. it->second.parse(object, ++data);
  50. } else {
  51. throw json::malformed_json_exception("Unexpected key " + key);
  52. }
  53. json::helper::advance_to_boundary('}', data);
  54. }
  55. if (*data) ++data;
  56. else throw json::malformed_json_exception("Reached end of parse string without finding object end");
  57. }
  58. template <typename E>
  59. object_binder& operator()(std::string const& s, E T::*p) {
  60. return operator()(s, binder<T>(new direct_binder<T, E>(p)));
  61. }
  62. private:
  63. std::map<std::string, binder<T>> mapping;
  64. };
  65. } }