JXXON object mapper library
Json.h
1 //
2 // Copyright (C) 2018 Dr. Michael Steffens
3 //
4 // SPDX-License-Identifier: BSL-1.0
5 //
6 
7 
8 #ifndef JXXON_Json_INCLUDED
9 #define JXXON_Json_INCLUDED
10 
11 #include <functional>
12 #include <memory>
13 #include <string>
14 
16 namespace JXXON {
17 
18 namespace Accessor {
19 
20 template<typename T, typename Enable = void>
21 class GetProperty;
22 
23 template<typename T, typename Enable = void>
24 class SetProperty;
25 
26 template<typename T, typename Enable = void>
27 class GetArrayElements;
28 
29 template<typename T, typename Enable = void>
30 class SetArrayElements;
31 
32 template<typename T, typename Enable = void>
33 class GetMapElements;
34 
35 template<typename T, typename Enable = void>
36 class SetMapElements;
37 
38 } // namespace Accessor
39 
68 class Json
69 {
70 public:
73  {
74  public:
76  virtual Json toJson() const = 0;
77  virtual ~Serializable()
78  {
79  }
80  };
81 
83  template<typename T>
84  class ArrayType
85  {
86  public:
89  {
90  }
91 
93  virtual void addElement(const T& element) = 0;
94 
96  virtual void forEach(const std::function<void(const T& element)>& f) const = 0;
97  };
98 
101  template<typename T, template<typename, typename...> class Base, typename... Args>
102  class Array : public Base<T, Args...>, public Serializable
103  {
104  public:
107  {
108  }
109 
111  explicit Array(typename Base<T, Args...>::size_type n) : Base<T, Args...>(n)
112  {
113  }
114 
116  Array(typename Base<T, Args...>::size_type n, const T& value) : Base<T, Args...>(n, value)
117  {
118  }
119 
121  template<typename InputIterator>
122  Array(InputIterator first, InputIterator last) : Base<T, Args...>(first, last)
123  {
124  }
125 
127  Array(const Array& other) : Base<T, Args...>(other)
128  {
129  }
130 
132  Array(Array&& other) : Base<T, Args...>(std::move(other))
133  {
134  }
135 
137  Array(std::initializer_list<T> initializerList) : Base<T, Args...>(initializerList)
138  {
139  }
140 
142  Array(const typename Base<T, Args...>::DelegateType& other) : Base<T, Args...>(other)
143  {
144  }
145 
147  Array(typename Base<T, Args...>::DelegateType&& other) : Base<T, Args...>(std::move(other))
148  {
149  }
150 
152  Array(const Json& json)
153  {
154  this->clear();
155  Accessor::GetArrayElements<T> get(json);
156  get(*this);
157  }
158 
161  {
162  }
163 
165  Array& operator=(const Array& other)
166  {
167  return static_cast<Array&>(Base<T, Args...>::operator=(other));
168  }
169 
172  {
173  return static_cast<Array&>(Base<T, Args...>::operator=(std::move(other)));
174  }
175 
177  Array& operator=(std::initializer_list<T> initializerList)
178  {
179  return static_cast<Array&>(Base<T, Args...>::operator=(initializerList));
180  }
181 
183  Array& operator=(const typename Base<T, Args...>::DelegateType& other)
184  {
185  return static_cast<Array&>(Base<T, Args...>::operator=(other));
186  }
187 
189  Array& operator=(typename Base<T, Args...>::DelegateType&& other)
190  {
191  return static_cast<Array&>(Base<T, Args...>::operator=(std::move(other)));
192  }
193 
194  virtual Json toJson() const override
195  {
196  JXXON::Json json;
197  Accessor::SetArrayElements<T> set(json);
198  set(*this);
199  return json;
200  }
201  };
202 
204  template<typename T>
205  class MapType
206  {
207  public:
210  {
211  }
212 
214  virtual void addElement(const std::string& key, const T& value) = 0;
215 
217  virtual void forEach(const std::function<void(const std::string& key, const T& value)>& f) const = 0;
218  };
219 
222  template<typename T, template<typename, typename...> class Base, typename... Args>
223  class Map : public Base<T, Args...>, public Serializable
224  {
225  public:
227  Map()
228  {
229  }
230 
232  template<typename InputIterator>
233  Map(InputIterator first, InputIterator last) : Base<T, Args...>(first, last)
234  {
235  }
236 
238  Map(const Map& other) : Base<T, Args...>(other)
239  {
240  }
241 
243  Map(Map&& other) : Base<T, Args...>(std::move(other))
244  {
245  }
246 
248  Map(std::initializer_list<std::pair<const std::string, T>> initializerList) : Base<T, Args...>(initializerList)
249  {
250  }
251 
253  Map(const typename Base<T, Args...>::DelegateType& other) : Base<T, Args...>(other)
254  {
255  }
256 
258  Map(typename Base<T, Args...>::DelegateType&& other) : Base<T, Args...>(std::move(other))
259  {
260  }
261 
263  Map(const Json& json)
264  {
265  this->clear();
266  Accessor::GetMapElements<T> get(json);
267  get(*this);
268  }
269 
272  {
273  }
274 
276  Map& operator=(const Map& other)
277  {
278  return static_cast<Map&>(Base<T, Args...>::operator=(other));
279  }
280 
282  Map& operator=(Map&& other)
283  {
284  return static_cast<Map&>(Base<T, Args...>::operator=(std::move(other)));
285  }
286 
288  Map& operator=(std::initializer_list<std::pair<const std::string, T>> initializerList)
289  {
290  return static_cast<Map&>(Base<T, Args...>::operator=(initializerList));
291  }
292 
294  Map& operator=(const typename Base<T, Args...>::DelegateType& other)
295  {
296  return static_cast<Map&>(Base<T, Args...>::operator=(other));
297  }
298 
300  Map& operator=(typename Base<T, Args...>::DelegateType&& other)
301  {
302  return static_cast<Map&>(Base<T, Args...>::operator=(std::move(other)));
303  }
304 
305  virtual Json toJson() const override
306  {
307  JXXON::Json json;
308  Accessor::SetMapElements<T> set(json);
309  set(*this);
310  return json;
311  }
312  };
313 
315  Json();
316 
317  Json(const Json& other) = delete;
318  Json& operator=(const Json& other) = delete;
319 
321  Json(Json&& other);
322 
324  Json(const std::string& document);
325 
327  Json& operator=(Json&& other);
328 
329  ~Json();
330 
332  bool isNull() const;
333 
335  std::string toString() const;
336 
338  template<typename T>
339  T get(const std::string& name) const
340  {
341  return Accessor::GetProperty<T>(*this, name)();
342  }
343 
345  template<typename T>
346  void set(const std::string& name, const T& value)
347  {
348  Accessor::SetProperty<T>(*this, name)(value);
349  }
350 
351  template<typename T, typename Enable>
352  friend class Accessor::GetProperty;
353 
354  template<typename T, typename Enable>
355  friend class Accessor::SetProperty;
356 
357  template<typename T, typename Enable>
358  friend class Accessor::GetArrayElements;
359 
360  template<typename T, typename Enable>
361  friend class Accessor::SetArrayElements;
362 
363  template<typename T, typename Enable>
364  friend class Accessor::GetMapElements;
365 
366  template<typename T, typename Enable>
367  friend class Accessor::SetMapElements;
368 
370  friend std::istream& operator>>(std::istream& in, Json& json);
371 
373  friend std::ostream& operator<<(std::ostream& out, const Json& json);
374 
375 private:
376  class Impl;
377  std::unique_ptr<Impl> pimpl;
378 
379  Json(std::unique_ptr<Impl>&& pimpl);
380 
381  void setTypeObject();
382  Json getChild(const std::string& name) const;
383  void setChild(const std::string& name, const Json& child);
384  void setTypeArray();
385  void append(const Json& element);
386  void append(const std::function<void(const Json& element)>& append) const;
387  void insert(const std::string& key, const Json& element);
388  void insert(const std::function<void(const std::string& key, const Json& element)>& insert) const;
389 };
390 
391 namespace Accessor {
392 
393 template<typename T>
394 class GetProperty<T, typename std::enable_if<std::is_base_of<Json::Serializable, T>::value>::type>
395 {
396 public:
397  GetProperty(const Json& json, const std::string& name) : json(json), name(name)
398  {
399  }
400 
401  T operator()() const
402  {
403  auto child(json.getChild(name));
404  return child.isNull() ? T() : T(child);
405  }
406 
407 private:
408  const Json& json;
409  const std::string& name;
410 };
411 
412 template<typename T>
413 class GetProperty<T, typename std::enable_if<std::is_convertible<T, std::shared_ptr<Json::Serializable>>::value>::type>
414 {
415 public:
416  GetProperty(const Json& json, const std::string& name) : json(json), name(name)
417  {
418  }
419 
420  T operator()() const
421  {
422  auto child(json.getChild(name));
423  return child.isNull() ? T() : std::make_shared<typename T::element_type>(child);
424  }
425 
426 private:
427  const Json& json;
428  const std::string& name;
429 };
430 
431 template<typename T>
432 class SetProperty<T, typename std::enable_if<std::is_base_of<Json::Serializable, T>::value>::type>
433 {
434 public:
435  SetProperty(Json& json, const std::string& name) : json(json), name(name)
436  {
437  json.setTypeObject();
438  }
439 
440  void operator()(const T& value)
441  {
442  json.setChild(name, value.toJson());
443  }
444 
445 private:
446  Json& json;
447  const std::string& name;
448 };
449 
450 template<typename T>
451 class SetProperty<T, typename std::enable_if<std::is_convertible<T, std::shared_ptr<Json::Serializable>>::value>::type>
452 {
453 public:
454  SetProperty(Json& json, const std::string& name) : json(json), name(name)
455  {
456  json.setTypeObject();
457  }
458 
459  void operator()(const T& value)
460  {
461  if (value) {
462  json.setChild(name, value->toJson());
463  }
464  }
465 
466 private:
467  Json& json;
468  const std::string& name;
469 };
470 
471 template<typename T>
472 class GetProperty<
473  T,
474  typename std::enable_if<
475  !std::is_base_of<Json::Serializable, T>::value &&
476  !std::is_convertible<T, std::shared_ptr<Json::Serializable>>::value>::type>
477 {
478 public:
479  GetProperty(const Json& json, const std::string& name);
480  T operator()() const;
481 
482 private:
483  const Json& json;
484  const std::string& name;
485 };
486 
487 template<typename T>
488 class SetProperty<
489  T,
490  typename std::enable_if<
491  !std::is_base_of<Json::Serializable, T>::value &&
492  !std::is_convertible<T, std::shared_ptr<Json::Serializable>>::value>::type>
493 {
494 public:
495  SetProperty(Json& json, const std::string& name);
496  void operator()(const T& value);
497 
498 private:
499  Json& json;
500  const std::string& name;
501 };
502 
503 template<typename T>
504 class GetArrayElements<T, typename std::enable_if<std::is_base_of<Json::Serializable, T>::value>::type>
505 {
506 public:
507  GetArrayElements(const Json& json) : json(json)
508  {
509  }
510 
511  void operator()(Json::ArrayType<T>& array) const
512  {
513  json.append([&array](const Json& element) { array.addElement(element.isNull() ? T() : T(element)); });
514  }
515 
516 private:
517  const Json& json;
518 };
519 
520 template<typename T>
521 class GetArrayElements<T, typename std::enable_if<std::is_convertible<T, std::shared_ptr<Json::Serializable>>::value>::type>
522 {
523 public:
524  GetArrayElements(const Json& json) : json(json)
525  {
526  }
527 
528  void operator()(Json::ArrayType<T>& array) const
529  {
530  json.append([&array](const Json& element) {
531  array.addElement(element.isNull() ? T() : std::make_shared<typename T::element_type>(element));
532  });
533  }
534 
535 private:
536  const Json& json;
537 };
538 
539 template<typename T>
540 class SetArrayElements<T, typename std::enable_if<std::is_base_of<Json::Serializable, T>::value>::type>
541 {
542 public:
543  SetArrayElements(Json& json) : json(json)
544  {
545  json.setTypeArray();
546  }
547 
548  void operator()(const Json::ArrayType<T>& array)
549  {
550  array.forEach([&](const T& element) { json.append(element.toJson()); });
551  }
552 
553 private:
554  Json& json;
555 };
556 
557 template<typename T>
558 class SetArrayElements<T, typename std::enable_if<std::is_convertible<T, std::shared_ptr<Json::Serializable>>::value>::type>
559 {
560 public:
561  SetArrayElements(Json& json) : json(json)
562  {
563  json.setTypeArray();
564  }
565 
566  void operator()(const Json::ArrayType<T>& array)
567  {
568  array.forEach([&](const T& element) { json.append(element ? element->toJson() : Json()); });
569  }
570 
571 private:
572  Json& json;
573 };
574 
575 template<typename T>
576 class GetArrayElements<
577  T,
578  typename std::enable_if<
579  !std::is_base_of<Json::Serializable, T>::value &&
580  !std::is_convertible<T, std::shared_ptr<Json::Serializable>>::value>::type>
581 {
582 public:
583  GetArrayElements(const Json& json);
584  void operator()(Json::ArrayType<T>& array) const;
585 
586 private:
587  const Json& json;
588 };
589 
590 template<typename T>
591 class SetArrayElements<
592  T,
593  typename std::enable_if<
594  !std::is_base_of<Json::Serializable, T>::value &&
595  !std::is_convertible<T, std::shared_ptr<Json::Serializable>>::value>::type>
596 {
597 public:
598  SetArrayElements(Json& json);
599  void operator()(const Json::ArrayType<T>& array);
600 
601 private:
602  Json& json;
603 };
604 
605 template<typename T>
606 class GetMapElements<T, typename std::enable_if<std::is_base_of<Json::Serializable, T>::value>::type>
607 {
608 public:
609  GetMapElements(const Json& json) : json(json)
610  {
611  }
612 
613  void operator()(Json::MapType<T>& map) const
614  {
615  json.insert(
616  [&map](const std::string& key, const Json& element) { map.addElement(key, element.isNull() ? T() : T(element)); });
617  }
618 
619 private:
620  const Json& json;
621 };
622 
623 template<typename T>
624 class GetMapElements<T, typename std::enable_if<std::is_convertible<T, std::shared_ptr<Json::Serializable>>::value>::type>
625 {
626 public:
627  GetMapElements(const Json& json) : json(json)
628  {
629  }
630 
631  void operator()(Json::MapType<T>& map) const
632  {
633  json.insert([&map](const std::string& key, const Json& element) {
634  map.addElement(key, element.isNull() ? T() : std::make_shared<typename T::element_type>(element));
635  });
636  }
637 
638 private:
639  const Json& json;
640 };
641 
642 template<typename T>
643 class SetMapElements<T, typename std::enable_if<std::is_base_of<Json::Serializable, T>::value>::type>
644 {
645 public:
646  SetMapElements(Json& json) : json(json)
647  {
648  json.setTypeObject();
649  }
650 
651  void operator()(const Json::MapType<T>& map)
652  {
653  map.forEach([&](const std::string& key, const T& value) { json.insert(key, value.toJson()); });
654  }
655 
656 private:
657  Json& json;
658 };
659 
660 template<typename T>
661 class SetMapElements<T, typename std::enable_if<std::is_convertible<T, std::shared_ptr<Json::Serializable>>::value>::type>
662 {
663 public:
664  SetMapElements(Json& json) : json(json)
665  {
666  json.setTypeObject();
667  }
668 
669  void operator()(const Json::MapType<T>& map)
670  {
671  map.forEach([&](const std::string& key, const T& value) { json.insert(key, value ? value->toJson() : Json()); });
672  }
673 
674 private:
675  Json& json;
676 };
677 
678 template<typename T>
679 class GetMapElements<
680  T,
681  typename std::enable_if<
682  !std::is_base_of<Json::Serializable, T>::value &&
683  !std::is_convertible<T, std::shared_ptr<Json::Serializable>>::value>::type>
684 {
685 public:
686  GetMapElements(const Json& json);
687  void operator()(Json::MapType<T>& map) const;
688 
689 private:
690  const Json& json;
691 };
692 
693 template<typename T>
694 class SetMapElements<
695  T,
696  typename std::enable_if<
697  !std::is_base_of<Json::Serializable, T>::value &&
698  !std::is_convertible<T, std::shared_ptr<Json::Serializable>>::value>::type>
699 {
700 public:
701  SetMapElements(Json& json);
702  void operator()(const Json::MapType<T>& map);
703 
704 private:
705  Json& json;
706 };
707 
708 } // namespace Accessor
709 
710 } // namespace JXXON
711 
712 #endif // JXXON_Json_INCLUDED */
Array & operator=(Array &&other)
Move assign array.
Definition: Json.h:171
Map(InputIterator first, InputIterator last)
Construct map with emplace constructed elements of range [first, last).
Definition: Json.h:233
Array & operator=(const typename Base< T, Args... >::DelegateType &other)
Copy assign delegate type array.
Definition: Json.h:183
Map & operator=(Map &&other)
Move assign map.
Definition: Json.h:282
Definition: Json.h:68
Interface implemented by JSON array type containers.
Definition: Json.h:84
Array & operator=(const Array &other)
Copy assign array.
Definition: Json.h:165
Definition: Json.h:223
~MapType()
Virtual destructor.
Definition: Json.h:209
Array(const Array &other)
Copy construct array.
Definition: Json.h:127
Map & operator=(typename Base< T, Args... >::DelegateType &&other)
Move assign delegate type map.
Definition: Json.h:300
virtual void forEach(const std::function< void(const T &element)> &f) const =0
Iterate through array.
JXXON root namespace.
Definition: Deque.h:14
Map(Map &&other)
Move construct map.
Definition: Json.h:243
Interface implemented by (de)serializable classes. Preferrably use the type alias JXXON::Serializable...
Definition: Json.h:72
virtual void addElement(const std::string &key, const T &value)=0
Add element to map.
Map & operator=(const Map &other)
Copy assign map.
Definition: Json.h:276
virtual void addElement(const T &element)=0
Add element to array. Ordered containers like vector or list must append element at the end...
Definition: Json.h:102
Array & operator=(typename Base< T, Args... >::DelegateType &&other)
Move assign delegate type array.
Definition: Json.h:189
Map & operator=(const typename Base< T, Args... >::DelegateType &other)
Copy assign delegate type map.
Definition: Json.h:294
~Array()
Virtual destructor.
Definition: Json.h:160
Array(typename Base< T, Args... >::DelegateType &&other)
Move construct array from delegate type.
Definition: Json.h:147
Array()
Construct empty array.
Definition: Json.h:106
Array(Array &&other)
Move construct array.
Definition: Json.h:132
Array(typename Base< T, Args... >::size_type n, const T &value)
Construct array of size n of copy of value constructed elements.
Definition: Json.h:116
Array(std::initializer_list< T > initializerList)
Initializer list constructor.
Definition: Json.h:137
Array(const Json &json)
Construct array from Json object.
Definition: Json.h:152
~ArrayType()
Virtual destructor.
Definition: Json.h:88
Array(typename Base< T, Args... >::size_type n)
Construct array of size n of default constructed elements.
Definition: Json.h:111
Array(InputIterator first, InputIterator last)
Construct array with emplace constructed elements of range [first, last).
Definition: Json.h:122
Map(const Map &other)
Copy construct map.
Definition: Json.h:238
Map(std::initializer_list< std::pair< const std::string, T >> initializerList)
Initializer list constructor.
Definition: Json.h:248
Map & operator=(std::initializer_list< std::pair< const std::string, T >> initializerList)
Initializer list assignment.
Definition: Json.h:288
virtual Json toJson() const override
Return Json object.
Definition: Json.h:194
bool isNull() const
Return true if object is representing a null value.
Map(const Json &json)
Construct map from Json object.
Definition: Json.h:263
Interface implemented by JSON map type containers.
Definition: Json.h:205
Map(typename Base< T, Args... >::DelegateType &&other)
Move construct map from delegate type.
Definition: Json.h:258
~Map()
Virtual destructor.
Definition: Json.h:271
Array(const typename Base< T, Args... >::DelegateType &other)
Copy construct array from delegate type.
Definition: Json.h:142
Map()
Construct empty map.
Definition: Json.h:227
Map(const typename Base< T, Args... >::DelegateType &other)
Copy construct map from delegate type.
Definition: Json.h:253
virtual Json toJson() const override
Return Json object.
Definition: Json.h:305
virtual void forEach(const std::function< void(const std::string &key, const T &value)> &f) const =0
Iterate through map.
Array & operator=(std::initializer_list< T > initializerList)
Initializer list assignment.
Definition: Json.h:177