json_direct_map_binder.hpp 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. //
  2. // json_direct_map_binder.hpp
  3. // json
  4. //
  5. // Created by Sam Jaffe on 4/23/16.
  6. //
  7. #pragma once
  8. #include "json_binder.hpp"
  9. #include "json_direct_binder.hpp"
  10. #include <map>
  11. namespace json { namespace binder {
  12. template <typename T, typename V, typename C>
  13. class associative_binder : public binder_impl<T> {
  14. public:
  15. associative_binder(C T::*p) : ptr(p), impl(value_binder<V>()) {}
  16. associative_binder(C T::*p, binder<V> const & i) : ptr(p), impl(i) {}
  17. virtual binder_impl<T> * clone() const override {
  18. return new associative_binder(*this);
  19. }
  20. virtual void parse(T & val, char const *& data,
  21. parser::options opts) const override {
  22. const char ch = json::helper::get_next_element(data);
  23. if (ch != '{') {
  24. throw json::malformed_json_exception("Expected an object type");
  25. }
  26. ++data;
  27. V to_make;
  28. C & map = val.*ptr;
  29. std::string key;
  30. while (*data && *data != '}') {
  31. json::helper::parse_string(key, data);
  32. if (json::helper::get_next_element(data) != ':') {
  33. throw malformed_object_association(*data);
  34. }
  35. impl.parse(to_make, ++data, opts);
  36. map.emplace(key, std::move(to_make));
  37. json::helper::advance_to_boundary('}', data);
  38. }
  39. if (*data)
  40. ++data;
  41. else
  42. throw unterminated_json_array();
  43. }
  44. virtual void write(T const & val, std::ostream & data) const override {
  45. data << '{';
  46. std::map<std::string, V> const & map = val.*ptr;
  47. auto it = map.begin(), end = map.end();
  48. if (it != end) {
  49. data << '"' << it->first << '"' << ':';
  50. impl.write(it->second, data);
  51. for (++it; it != end; ++it) {
  52. data << ',';
  53. data << '"' << it->first << '"' << ':';
  54. impl.write(it->second, data);
  55. }
  56. }
  57. data << '}';
  58. }
  59. private:
  60. std::map<std::string, V> T::*ptr;
  61. binder<V> impl;
  62. };
  63. #define ASSOCIATIVE_DIRECT_BINDER(C) \
  64. template <typename T, typename V, typename... O> \
  65. class direct_binder<T, C<std::string, V, O...>> \
  66. : public associative_binder<T, V, C<std::string, V, O...>> { \
  67. public: \
  68. using associative_binder<T, V, \
  69. C<std::string, V, O...>>::associative_binder; \
  70. }
  71. ASSOCIATIVE_DIRECT_BINDER(std::map);
  72. // ASSOCIATIVE_DIRECT_BINDER( std::unordered_map );
  73. }}