json_direct_map_binder.hpp 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  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) ++data;
  40. else throw unterminated_json_array();
  41. }
  42. virtual void write(T const& val, std::ostream & data) const override {
  43. data << '{';
  44. std::map<std::string, V> const & map = val.*ptr;
  45. auto it = map.begin(), end = map.end();
  46. if (it != end) {
  47. data << '"' << it->first << '"' << ':';
  48. impl.write(it->second, data);
  49. for (++it; it != end; ++it) {
  50. data << ',';
  51. data << '"' << it->first << '"' << ':';
  52. impl.write(it->second, data);
  53. }
  54. }
  55. data << '}';
  56. }
  57. private:
  58. std::map<std::string, V> T::*ptr;
  59. binder<V> impl;
  60. };
  61. #define ASSOCIATIVE_DIRECT_BINDER( C ) \
  62. template <typename T, typename V, typename... O> \
  63. class direct_binder<T, C<std::string, V, O...> > : \
  64. public associative_binder<T, V, C<std::string, V, O...>> { \
  65. public: \
  66. using associative_binder<T,V,C<std::string,V,O...>>::associative_binder; \
  67. }
  68. ASSOCIATIVE_DIRECT_BINDER( std::map );
  69. // ASSOCIATIVE_DIRECT_BINDER( std::unordered_map );
  70. } }