json_direct_map_binder.hpp 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. //
  2. // json_direct_map_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, typename V, typename C>
  10. class associative_binder : public binder_impl<T> {
  11. public:
  12. associative_binder(C T::*p) : ptr(p), impl(value_binder<V>()) {}
  13. associative_binder(C T::*p, binder<V> const & i) : ptr(p), impl(i) {}
  14. virtual binder_impl<T>* clone() const override { return new associative_binder(*this); }
  15. virtual void parse(T& val, char const*& data, parser::options opts) const override {
  16. const char ch = json::helper::get_next_element(data);
  17. if (ch != '{') {
  18. throw json::malformed_json_exception("Expected an object type");
  19. }
  20. ++data;
  21. V to_make;
  22. C & map = val.*ptr;
  23. std::string key;
  24. while (*data && *data != '}') {
  25. json::helper::parse_string(key, data);
  26. if (json::helper::get_next_element(data) != ':') {
  27. throw json::malformed_json_exception(std::string("Expected key:value pair delimited by ':', got '") + *data + "' instead");
  28. }
  29. impl.parse(to_make, ++data, opts);
  30. map.emplace(key, std::move(to_make));
  31. json::helper::advance_to_boundary('}', data);
  32. }
  33. if (*data) ++data;
  34. else throw json::unterminated_json_exception("Reached end of parse string without finding object end");
  35. }
  36. virtual void write(T const& val, std::ostream & data) const override {
  37. data << '{';
  38. std::map<std::string, V> const & map = val.*ptr;
  39. typename std::map<std::string, V>::const_iterator it = map.begin(), end = map.end();
  40. if (it != end) {
  41. data << '"' << it->first << '"' << ':';
  42. impl.write(it->second, data);
  43. for (++it; it != end; ++it) {
  44. data << ',';
  45. data << '"' << it->first << '"' << ':';
  46. impl.write(it->second, data);
  47. }
  48. }
  49. data << '}';
  50. }
  51. private:
  52. std::map<std::string, V> T::*ptr;
  53. binder<V> impl;
  54. };
  55. #define ASSOCIATIVE_DIRECT_BINDER( C ) \
  56. template <typename T, typename V, typename... O> \
  57. class direct_binder<T, C<std::string, V, O...> > : \
  58. public associative_binder<T, V, C<std::string, V, O...>> { \
  59. public: \
  60. using associative_binder<T, V, C<std::string, V, O...>>::associative_binder; \
  61. }
  62. ASSOCIATIVE_DIRECT_BINDER( std::map );
  63. // ASSOCIATIVE_DIRECT_BINDER( std::unordered_map );
  64. } }