MIRA
JSONSerializer.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2012 by
3  * MetraLabs GmbH (MLAB), GERMANY
4  * and
5  * Neuroinformatics and Cognitive Robotics Labs (NICR) at TU Ilmenau, GERMANY
6  * All rights reserved.
7  *
8  * Contact: info@mira-project.org
9  *
10  * Commercial Usage:
11  * Licensees holding valid commercial licenses may use this file in
12  * accordance with the commercial license agreement provided with the
13  * software or, alternatively, in accordance with the terms contained in
14  * a written agreement between you and MLAB or NICR.
15  *
16  * GNU General Public License Usage:
17  * Alternatively, this file may be used under the terms of the GNU
18  * General Public License version 3.0 as published by the Free Software
19  * Foundation and appearing in the file LICENSE.GPL3 included in the
20  * packaging of this file. Please review the following information to
21  * ensure the GNU General Public License version 3.0 requirements will be
22  * met: http://www.gnu.org/copyleft/gpl.html.
23  * Alternatively you may (at your option) use any later version of the GNU
24  * General Public License if such license has been publicly approved by
25  * MLAB and NICR (or its successors, if any).
26  *
27  * IN NO EVENT SHALL "MLAB" OR "NICR" BE LIABLE TO ANY PARTY FOR DIRECT,
28  * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF
29  * THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF "MLAB" OR
30  * "NICR" HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  * "MLAB" AND "NICR" SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
33  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
34  * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
35  * ON AN "AS IS" BASIS, AND "MLAB" AND "NICR" HAVE NO OBLIGATION TO
36  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR MODIFICATIONS.
37  */
38 
47 #ifndef _MIRA_JSONSERIALIZER_H_
48 #define _MIRA_JSONSERIALIZER_H_
49 
50 #include <iostream>
51 #include <list>
52 #include <algorithm>
53 #include <stack>
54 
57 
58 #include <json/JSON.h>
59 
61 
62 namespace mira {
63 
65 
93 class JSONSerializer : public Serializer<JSONSerializer>
94 {
96 
97 public:
100  {
102  STANDARD = 0x00,
103 
106  };
107 
108  MIRA_ENUM_TO_FLAGS_INCLASS(OutputFormat) // generate logical operators for enum values
109 
110 
115  JSONSerializer(bool readOnly = false, OutputFormat format = STANDARD)
116  : mReadOnly(readOnly), mOutputFormat(format)
117  {}
118 
120  template<typename T>
121  json::Value serialize(const T& value)
122  {
123  mFirstComplex = true;
124  auto jvalue = json::Value();
125  mValuePtr = &jvalue;
127  return jvalue;
128  }
129 
130  json::Value serialize(const json::Value& value)
131  {
132  return value;
133  }
134 
136 
137  template<typename T>
138  VersionType version(VersionType version, const T* caller = NULL)
139  {
140  return this->version<T>(version, false);
141  }
142 
143  MIRA_DEPRECATED("Please call as version<MyType>(v) or version(v, this)",
145  {
146  return versionLegacy(version);
147  }
148 
149  template<typename T>
151  {
152  return this->version<T>(version, true);
153  }
154 
155 private:
156  template<typename T>
157  VersionType version(VersionType version, bool acceptDesiredVersion)
158  {
159  version = this->template queryDesiredClassVersion<T>(version, acceptDesiredVersion);
160 
161  int vf = this->forcedSerializeVersion();
162  if ((vf == 0) || (vf == 1))
163  return versionLegacy(version);
164 
165  static const std::string v = std::string("@version[") + typeName<T>() + "]";
166  mValuePtr->get_obj()[v] = json::Value(json::cast(version));
167  return version;
168  }
169 
170  VersionType versionLegacy(VersionType version)
171  {
172  mValuePtr->get_obj()["@version"] = json::Value(json::cast((int)version));
173  return version;
174  }
175 
176 public:
177  template<typename T>
178  void atomic(T& member)
179  {
180  // member of a currently serialized object -> add member
181  if (mValuePtr->type() == json_spirit::obj_type) {
182  mValuePtr->get_obj()[getCurrentMemberMeta().id] = json::Value(json::cast(member));
183  }
184  // item of a currently serialized array -> add item
185  else if (mValuePtr->type() == json_spirit::array_type) {
186  mValuePtr->get_array().push_back(json::Value(json::cast(member)));
187  }
188  // no currently serialized value -> set member as new value
189  else {
190  *mValuePtr = json::Value(json::cast(member));
191  }
192  }
193 
195  {
196  // member of a currently serialized object -> add member
197  if (mValuePtr->type() == json_spirit::obj_type) {
198  mValuePtr->get_obj()[getCurrentMemberMeta().id] = member;
199  }
200  // item of a currently serialized array -> add item
201  else if (mValuePtr->type() == json_spirit::array_type) {
202  mValuePtr->get_array().push_back(member);
203  }
204  // no currently serialized value -> set member as new value
205  else {
206  *mValuePtr = member;
207  }
208  }
209 
210  template<typename T>
211  void object(T& member)
212  {
213  // in json the outer most object (the root object) has no name
214  if (mFirstComplex) {
215  *mValuePtr = json::Object();
216  mFirstComplex = false;
217  if (!mPointerClass.empty()) {
218  mValuePtr->get_obj()["@class"] = json::Value(mPointerClass);
219  mPointerClass.clear();
220  }
222  }
223  else {
224  json::Value* oldValue = mValuePtr;
225 
226  if (oldValue->type() == json_spirit::obj_type) {
227  json::Value& entry = oldValue->get_obj()[getCurrentMemberMeta().id];
228  entry = json::Object();
229  mValuePtr = &entry;
230  }
231  else if (oldValue->type() == json_spirit::array_type) {
232  oldValue->get_array().push_back(json::Object());
233  json::Value& entry = oldValue->get_array().back();
234  mValuePtr = &entry;
235  }
236 
237  if (!mPointerClass.empty()) {
238  mValuePtr->get_obj()["@class"] = json::Value(mPointerClass);
239  mPointerClass.clear();
240  }
242  mValuePtr = oldValue;
243  }
244  }
245 
246  template<typename T>
248  {
249  collectionInternal(member);
250  }
251 
252  template<template<typename U, typename V> class MapType, typename T>
253  typename std::enable_if_t<std::is_same_v<T, typename MapType<std::string, T>::mapped_type>,
254  void> collection(MapType<std::string, T>& member)
255  {
256  if (mOutputFormat & STRING_MAP_AS_OBJECT)
257  object(member);
258  else
259  collectionInternal(member);
260  }
261 
262  void pointerReference(int referencedObjectID)
263  {
264  json::Value val = json::Object();
265  val.get_obj()["@ref"] = json::Value(this->getHumanReadableFullID(referencedObjectID));
266  if (mValuePtr->type() == json_spirit::obj_type)
267  mValuePtr->get_obj()[getCurrentMemberMeta().id] = val;
268  else if (mValuePtr->type() == json_spirit::array_type)
269  mValuePtr->get_array().push_back(val);
270  }
271 
272  void pointerWithClassType(const std::string& type)
273  {
274  mPointerClass = type;
275  }
276 
277  void pointerNull()
278  {
279  if (mValuePtr->type() == json_spirit::obj_type)
280  mValuePtr->get_obj()[getCurrentMemberMeta().id] = json::Value();
281  else if (mValuePtr->type() == json_spirit::array_type)
282  mValuePtr->get_array().push_back(json::Value());
283  else
284  *mValuePtr = json::Value();
285  }
286 
287  template<typename T>
288  void roproperty(const char* name, const T& member, const char* comment,
290  {
291  if (!mReadOnly)
292  return;
293  // cast away constness, this is okay, since read only properties we
294  // will never write to the data
295  property(name, const_cast<T&>(member), comment, std::move(hint), flags);
296  }
297 
298  template<typename T>
299  void roproperty(const char* name, const std::string& id, const T& member, const char* comment,
301  {
302  if (!mReadOnly)
303  return;
304  // cast away constness, this is okay, since read only properties we
305  // will never write to the data
306  property(name, id, const_cast<T&>(member), comment, std::move(hint), flags);
307  }
308 
309  template<typename T>
310  void roproperty(const char* name, Getter<T> getter, const char* comment,
312  {
313  if (!mReadOnly)
314  return;
315  auto a = makeAccessor(getter, NullSetter<T>());
316  property(name, a, comment, std::move(hint), flags);
317  }
318 
319 public:
320  template<typename Container>
321  void mapEntry(int id, const typename Container::value_type& p)
322  {
323  using type = typename Container::mapped_type;
324 
325  if (mOutputFormat & STRING_MAP_AS_OBJECT) {
326  type& nonconstv = const_cast<type&>(p.second);
327  member(p.first.c_str(), nonconstv, "");
328  }
329  else {
330  serialization::reflectReadMapPair<JSONSerializer, Container>(*this, "item", id, p);
331  }
332  }
333 
334 private:
335  template<typename T>
336  void collectionInternal(T& member)
337  {
338  if (mFirstComplex) {
339  *mValuePtr = json::Array{};
340  mFirstComplex = false;
342  }
343  else {
344  json::Value* oldValue = mValuePtr;
345 
346  if (oldValue->type() == json_spirit::obj_type) {
347  json::Value& entry = oldValue->get_obj()[getCurrentMemberMeta().id];
348  entry = json::Array{};
349  mValuePtr = &entry;
350  }
351  else if (oldValue->type() == json_spirit::array_type) {
352  oldValue->get_array().push_back(json::Array{});
353  json::Value& entry = oldValue->get_array().back();
354  mValuePtr = &entry;
355  }
356  // serialize to adress of mValuePtr
358  mValuePtr = oldValue;
359  }
360  }
361 
362 private:
363  bool mFirstComplex;
364  bool mReadOnly;
365  json::Value* mValuePtr;
366  std::string mPointerClass;
367 
368  OutputFormat mOutputFormat;
369 };
370 
372 
401 class JSONDeserializer : public Deserializer<JSONDeserializer>
402 {
404 
405 public:
406 
409  {
411  STANDARD = 0x00,
412 
418  };
419 
420  MIRA_ENUM_TO_FLAGS_INCLASS(InputFormat) // generate logical operators for enum values
421 
423  mValue(&value), mStringMapAsObject(false), mInputFormat(format)
424  {
425  }
426 
427  template <typename T>
428  void deserialize(T& value)
429  {
430  mIndex = 0;
431  mFirstComplex = true;
433  }
434 
436  {
437  value = *mValue;
438  }
439 
440  const json::Value* getMember(const json::Value* value, const std::string& name)
441  {
442  if (value->get_obj().count(name) == 0)
443  MIRA_THROW(XMemberNotFound, "Missing member '" << name
444  << "' (" << getCurrentMemberFullID()
445  << ") while deserializing object='" << json::write(*mValue));
446  return &value->get_obj().at(name);
447  }
448 
449  const json::Value* getItem(const json::Value* value, std::size_t index)
450  {
451  if (value->get_array().size() <= index)
452  MIRA_THROW(XMemberNotFound, "Missing item[" << index
453  << "] (" << getCurrentMemberFullID()
454  << ") while deserializing collection='" << json::write(*mValue));
455  return &value->get_array()[index];
456  }
457 
459 
460  template <typename T>
461  VersionType version(VersionType expectedVersion, const T* object = NULL)
462  {
463  int vf = this->forcedDeserializeVersion();
464  if ((vf == 0) || (vf == 1))
465  return versionLegacy(expectedVersion);
466 
467  static const std::string v = std::string("@version[") + typeName<T>() + "]";
468  return getVersion<T>(expectedVersion, v);
469  }
470 
471  MIRA_DEPRECATED("Please call as version<MyType>(v) or version(v, this)",
472  VersionType version(VersionType expectedVersion))
473  {
474  return versionLegacy(expectedVersion);
475  }
476 
477  template <typename T>
478  VersionType version(VersionType expectedVersion, AcceptDesiredVersion, const T* caller = NULL)
479  {
480  return this->version<T>(expectedVersion);
481  }
482 
483 private:
484 
485  VersionType versionLegacy(VersionType expectedVersion)
486  {
487  return getVersion<void>(expectedVersion, "@version");
488  }
489 
490  template <typename T>
491  VersionType getVersion(VersionType expectedVersion, const std::string& versionElement)
492  {
493  if (mValue->get_obj().count(versionElement) == 0)
494  return 0;
495  VersionType version = mValue->get_obj().at(versionElement).get_value<json::TypeTrait<int>::type >();
496  if (version > expectedVersion) {
497  MIRA_LOG(WARNING) << "Trying to deserialize JSON data of a newer version (" << (int)version <<
498  ") of type " << typeName<T>() << " into an older version (" << (int)expectedVersion << ").";
499  }
500  return version;
501  }
502 
503 public:
504 
505  template<typename T>
506  void atomic(T& member)
507  {
508  if ( mValue->type() == json_spirit::obj_type )
509  {
510  const json::Value* item = getMember(mValue, mCurrentMemberID);
511  try {
512  member = json::reverse_cast<T>(item->get_value<typename json::TypeTrait<T>::type >());
513  }
514  catch(std::exception& ex)
515  {
516  MIRA_THROW(XInvalidConfig, "Error deserializing member '" << mCurrentMemberID
517  << "' (" << getCurrentMemberFullID()
518  << ") from object='" << json::write(*mValue)
519  << "' as " << typeName<T>() << ": " << ex.what());
520  }
521  }
522  else if ( mValue->type() == json_spirit::array_type )
523  {
524  const json::Value* item = getItem(mValue, mIndex++);
525  try {
526  member = json::reverse_cast<T>(item->get_value<typename json::TypeTrait<T>::type >());
527  }
528  catch(std::exception& ex)
529  {
530  MIRA_THROW(XInvalidConfig, "Error deserializing item[" << mIndex-1
531  << "] (" << getCurrentMemberFullID()
532  << ") from collection='" << json::write(*mValue)
533  << "' as " << typeName<T>() << ": " << ex.what());
534  }
535  }
536  else
537  {
538  try
539  {
540  member = json::reverse_cast<T>(mValue->get_value<typename json::TypeTrait<T>::type>());
541  }
542  catch(std::exception& ex)
543  {
544  MIRA_THROW(XMemberNotFound, "Error deserializing atomic (" << getCurrentMemberFullID()
545  << ") with content='" << json::write(*mValue) << "' as " << typeName<T>() << ": " << ex.what());
546  }
547  }
548  }
549 
551  {
552  if ( mValue->type() == json_spirit::obj_type )
553  member = *getMember(mValue, mCurrentMemberID);
554  else if ( mValue->type() == json_spirit::array_type )
555  member = *getItem(mValue, mIndex++);
556  else
557  member = *mValue;
558  }
559 
560  template<typename T>
561  void object(T& member)
562  {
563  if ( mFirstComplex )
564  {
565  mFirstComplex = false;
567  return;
568  }
569  const json::Value* oldValue = mValue;
570  std::size_t oldIndex = mIndex;
571  if ( mValue->type() == json_spirit::obj_type )
572  {
573  mValue = getMember(mValue, mCurrentMemberID);
574  }
575  else if ( mValue->type() == json_spirit::array_type )
576  {
577  mValue = getItem(mValue, oldIndex);
578  mIndex = 0;
579  }
580 
582 
583  mValue = oldValue;
584  mIndex = oldIndex+1;
585  }
586 
587  template<typename T>
589  {
590  collectionInternal(member);
591  }
592 
593  template<template<typename U, typename V> class MapType, typename T>
594  typename std::enable_if_t<std::is_same_v<T, typename MapType<std::string, T>::mapped_type>,
595  void> collection(MapType<std::string, T>& member)
596  {
597  if (!(mInputFormat & ACCEPT_STRING_MAP_AS_OBJECT)) {
598  collectionInternal(member);
599  return;
600  }
601 
602  if (mStringMapAsObject) {
603  json::Object::const_iterator oldCurrentStringMapMember = mCurrentStringMapMember;
604  object(member);
605  mCurrentStringMapMember = oldCurrentStringMapMember;
606  return;
607  }
608 
609  assert(mStringMapAsObject == false);
610 
611  // backup deserializer state
612  const json::Value* oldValue = mValue;
613  std::size_t oldIndex = mIndex;
614  std::string memberID = mCurrentMemberID;
615  bool firstComplex = mFirstComplex;
616 
618  ObjectsVector trackingInstances = mObjects;
619 
620  try {
621  try {
622  collectionInternal(member);
623  }
624  catch (XInvalidConfig& ex) {
625  MIRA_LOG(DEBUG) << "Deserialize map<string, T> as array failed, try as object:" << std::endl;
626 
627  // reset deserializer state to state before calling collection(), and try again, calling object()
628  mObjectNameToInstance = trackingNames;
629  mObjects = trackingInstances;
630 
631  mValue = oldValue;
632  mIndex = oldIndex;
633  mCurrentMemberID = memberID;
634  mFirstComplex = firstComplex;
635 
636  MIRA_LOG(DEBUG) << json::write(*mValue) << std::endl;
637 
638  mStringMapAsObject = true;
639  object(member);
640  }
641  }
642  // make sure we get to reset mStringMapAsObject as final statement on our way "up"
643  catch(Exception& ex) {
644  mStringMapAsObject = false;
645  MIRA_RETHROW(ex, "While trying to deserialize MapType<string, T> as object.");
646  }
647  catch(...) {
648  mStringMapAsObject = false;
649  throw;
650  }
651 
652  mStringMapAsObject = false;
653  }
654 
656  {
657  const json::Array* array;
658  try
659  {
660  array = &mValue->get_array();
661  }
662  catch(std::exception& ex)
663  {
664  MIRA_THROW(XInvalidConfig, "Error deserializing collection (" << getCurrentMemberFullID()
665  << ") from json::Value='" << json::write(*mValue) << "': " << ex.what());
666  }
667  return array;
668  }
669 
670  template<typename T>
671  void pointer(T* &pointer)
672  {
673  const json::Value* value;
674  if ( mFirstComplex )
675  value = mValue;
676  else
677  {
678  if ( mValue->type() == json_spirit::obj_type )
679  value = getMember(mValue, mCurrentMemberID);
680  else if ( mValue->type() == json_spirit::array_type )
681  value = getItem(mValue, mIndex);
682  }
683 
684  std::size_t oldIndex = mIndex;
685 
686  // do we have a null pointer?
687  if(value->is_null()) {
688  pointer = NULL;
689  }
690  // do we have a reference?
691  else {
692  assert(value->type() == json_spirit::obj_type);
693  auto it = value->get_obj().find("@ref");
694  if(it!=value->get_obj().end()) {
695  // we have a reference, so resolve it
696  pointer = resolveReference<T>(it->second.get_value<std::string>());
697  } else {
698  // we have a "normal" pointer, so deserialize it
700  }
701  }
702 
703  if (mValue->type() == json_spirit::array_type)
704  mIndex = oldIndex+1;
705  }
706 
707  std::string pointerClassType()
708  {
709  const json::Value* value;
710  if ( mFirstComplex )
711  value = mValue;
712  else
713  {
714  if ( mValue->type() == json_spirit::obj_type )
715  {
716  try
717  {
718  value = getMember(mValue, mCurrentMemberID);
719  }
720  catch(XMemberNotFound& ex)
721  {
722  MIRA_RETHROW(ex, "Error getting pointer class type of member '"
723  << mCurrentMemberID << "' (" << getCurrentMemberFullID()
724  << ") from object='" << json::write(*mValue)<< "'");
725  }
726  }
727  else if ( mValue->type() == json_spirit::array_type )
728  {
729  try
730  {
731  value = getItem(mValue, mIndex);
732  }
733  catch(XMemberNotFound& ex)
734  {
735  MIRA_RETHROW(ex, "Error getting pointer class type of item[" << mIndex
736  << "] (" << getCurrentMemberFullID()
737  << ") from collection='" << json::write(*mValue) << "'");
738  }
739  }
740  }
741  if(value->type() == json_spirit::obj_type)
742  {
743  auto it = value->get_obj().find("@class");
744  if(it!=value->get_obj().end())
745  return it->second.get_value<std::string>();
746  }
747  return "Unknown Class";
748  }
749 
750  // hijack the invokeOverwrite method for adding a starting and closing tag
751  // around the serialized data
752  template<typename T>
754  {
755  std::string oldID = mCurrentMemberID;
756  if(meta.id!=NULL)
757  mCurrentMemberID = meta.id;
758  try
759  {
761  }
762  catch(...)
763  {
764  if(meta.id!=NULL)
765  mCurrentMemberID = oldID;
766  throw;
767  }
768  if(meta.id!=NULL)
769  mCurrentMemberID = oldID;
770  }
771 
772 public:
773 
775  {
776  if (mStringMapAsObject) {
777  try {
778  const json::Object* o = &mValue->get_obj();
779  mCurrentStringMapMember = mValue->get_obj().begin();
780  return (uint32)o->size();
781  }
782  catch(std::exception& ex)
783  {
784  MIRA_THROW(XInvalidConfig, "Error counting object elements from json::Value='"
785  << json::write(*mValue) << "': " << ex.what());
786  }
787  } else {
788  const json::Array* a = getCollection();
789  return (uint32)a->size();
790  }
791  }
792 
793  template<typename Container>
794  void mapEntry(int id, Container& c, typename Container::iterator& hint)
795  {
796  typedef typename Container::value_type value_type;
797  typedef typename Container::mapped_type mapped_type;
798 
799  if (mStringMapAsObject) {
800  std::string key = mCurrentStringMapMember->first;
801  hint = c.insert(hint, value_type(key, mapped_type()));
802  property(key.c_str(), hint->second, "");
803  ++mCurrentStringMapMember;
804  } else {
805  serialization::reflectWriteMapPair(*this, "item", "key", id, c, hint);
806  }
807  }
808 
809 private:
810  template<typename T>
811  void collectionInternal(T& member)
812  {
813  if ( mFirstComplex )
814  {
815  mFirstComplex = false;
817  return;
818  }
819  const json::Value* oldValue = mValue;
820  std::size_t oldIndex = mIndex;
821  if ( mValue->type() == json_spirit::obj_type )
822  {
823  mValue = getMember(mValue, mCurrentMemberID);
824  mIndex = 0;
825  }
826  else if ( mValue->type() == json_spirit::array_type )
827  {
828  mValue = getItem(mValue, oldIndex);
829  mIndex = 0;
830  }
831 
833 
834  mValue = oldValue;
835  mIndex = oldIndex+1;
836  }
837 
838 private:
839  bool mFirstComplex;
840  std::size_t mIndex;
841  const json::Value* mValue;
842  std::string mCurrentMemberID;
843 
844  bool mStringMapAsObject;
845  json::Object::const_iterator mCurrentStringMapMember;
846 
847  InputFormat mInputFormat;
848 };
849 
850 namespace serialization { // our private namespace
851 
853 
861 template<typename Collection>
863 {
864  static void reflect(JSONSerializer& r, uint32& ioCount)
865  {
866  // do nothing
867  }
868 };
869 
876 template<typename Collection>
878 {
879  static void reflect(JSONDeserializer& r, uint32& ioCount)
880  {
881  const json::Array* a = r.getCollection();
882  ioCount = (uint32)a->size();
883  }
884 };
885 
886 namespace SpecializeForMapped_Type {
887 
889 
890 template<typename Collection, typename T, typename HasMappedType = std::true_type>
892 {
893  static void reflect(JSONDeserializer& r, uint32& ioCount)
894  {
895  const json::Array* a = r.getCollection();
896  ioCount = (uint32)a->size();
897  }
898 };
899 
900 // If Collection::mapped_type exists and equals T, this specialization 'overrides' the definition above.
901 // Otherwise, this just does not exist (if Collection::mapped_type cannot be resolved, SFINAE, no error),
902 // or will be ignored (unless the third template parameter is explicitly given, which we should not do).
903 template<typename Collection, typename T>
904 struct ReflectCollectionCount<Collection, T,
905  typename std::is_same<T, typename Collection::mapped_type>::type>
906 {
907  static void reflect(JSONDeserializer& r, uint32& ioCount)
908  {
909  ioCount = r.getStringMapElementCount();
910  }
911 };
912 
914 
915 }
916 
922 template<template<typename U, typename V> class MapType, typename T>
923 struct ReflectCollectionCount<JSONDeserializer, MapType<std::string, T>>
924  : public SpecializeForMapped_Type::ReflectCollectionCount<MapType<std::string, T>, T>
925 {
926 };
927 
928 // ReflectReadMapItems/ReflectWriteMapItems must be applicable to generic map types (with string key),
929 // but there is no need to explicitly check for the existence of mapped_type, since these are not
930 // applied based on the more general IsCollection type trait, but only for types which
931 // define it explicitly (like std::map and std::unordered_map).
932 
933 template<template<typename U, typename V> class MapType, typename mapped_type>
934 struct ReflectReadMapItems<JSONSerializer, MapType<std::string, mapped_type>>
935 {
936  typedef MapType<std::string, mapped_type> Container;
937  typedef typename Container::value_type value_type;
938 
939  static void reflect(JSONSerializer& r, Container& c)
940  {
941  // store each item
942  int id=0;
943  foreach(value_type& p, c)
944  {
945  r.mapEntry<Container>(id, p);
946  ++id;
947  }
948  }
949 };
950 
951 template<template<typename U, typename V> class MapType, typename mapped_type>
952 struct ReflectWriteMapItems<JSONDeserializer, MapType<std::string, mapped_type>>
953 {
954  typedef MapType<std::string, mapped_type> Container;
955  typedef typename Container::iterator iterator;
956 
957  static void reflect(JSONDeserializer& r, Container& c, uint32 count)
958  {
959  iterator hint = c.begin();
960 
961  // restore each item and insert into the map
962  for(uint32 id=0; id<count; ++id)
963  r.mapEntry<Container>(id, c, hint);
964  }
965 };
966 
968 
969 }
970 
972 
973 } // namespace
974 
975 #endif
Serializer for serializing objects in JSON format.
Definition: JSONSerializer.h:93
void write(const Value &value, std::ostream &ioStream, bool formatted=false, int precision=-1)
Writes a json::Value into a given stream using the JSON format.
void deserialize(T &value)
Definition: JSONSerializer.h:428
Base::VersionType VersionType
Definition: JSONSerializer.h:458
void object(T &member)
Is called for each complex object.
Definition: RecursiveMemberReflector.h:321
void pointer(T *&pointer)
Definition: JSONSerializer.h:671
InputFormat
Flags for JSON input format.
Definition: JSONSerializer.h:408
void pointerNull()
Definition: JSONSerializer.h:277
TEigenFormat< Derived > format(Eigen::MatrixBase< Derived > &matrix, Eigen::IOFormat format=EigenFormat::matlab())
Function for formatting an Eigen matrix using a special format.
Definition: EigenFormat.h:522
static void reflect(JSONDeserializer &r, Container &c, uint32 count)
Definition: JSONSerializer.h:957
void roproperty(const char *name, const T &member, const char *comment, PropertyHint &&hint=PropertyHint(), ReflectCtrlFlags flags=REFLECT_CTRLFLAG_NONE)
Definition: JSONSerializer.h:288
void mapEntry(int id, Container &c, typename Container::iterator &hint)
Definition: JSONSerializer.h:794
Contains the Serializer template, a base class for all serializers.
void pointer(T *&pointer)
Definition: Deserializer.h:157
void deserialize(const std::string &name, T &value)
Deserializes the specified object value with the given name.
Definition: Deserializer.h:133
void roproperty(const char *name, Getter< T > getter, const char *comment, PropertyHint &&hint=PropertyHint(), ReflectCtrlFlags flags=REFLECT_CTRLFLAG_NONE)
Definition: JSONSerializer.h:310
void reflectWriteMapPair(Derived &r, const char *itemName, const char *keyName, uint32 id, Container &c, typename Container::iterator &ioHint)
Definition: StlCollections.h:324
json_spirit::mArray Array
A representation of an array (vector) in JSON.
Definition: JSON.h:188
std::enable_if_t< std::is_same_v< T, typename MapType< std::string, T >::mapped_type >, void > collection(MapType< std::string, T > &member)
Definition: JSONSerializer.h:595
typename ReflectorInterface< JSONSerializer >::AcceptDesiredVersion AcceptDesiredVersion
Definition: AbstractReflector.h:195
specialize cv::DataType for our ImgPixel and inherit from cv::DataType<Vec>
Definition: IOService.h:67
const std::string & getCurrentMemberFullID() const
Returns the full human readable object id / name of the current member being reflected.
Definition: RecursiveMemberReflector.h:490
void member(const char *name, T &member, const char *comment, ReflectCtrlFlags flags=REFLECT_CTRLFLAG_NONE)
Definition: RecursiveMemberReflector.h:883
const std::string & getHumanReadableFullID(int objectID) const
Returns the full human readable object id / name for the given internal objectID. ...
Definition: Serializer.h:465
void atomic(json::Value &member)
Definition: JSONSerializer.h:550
static int forcedDeserializeVersion()
Returns either the version number from value of environment variable &#39;MIRA_FORCE_DESERIALIZE_VERSION&#39;...
Definition: Deserializer.h:118
Is a special reflector that is used for serialization.
Definition: Serializer.h:126
#define MIRA_LOG(level)
Use this macro to log data.
Definition: LoggingCore.h:529
STL namespace.
uint32_t uint32
Definition: Types.h:64
#define MIRA_RETHROW(ex, msg)
Macro for rethrowing an exception with file and line information and for adding additional informatio...
Definition: Exception.h:144
void collection(T &member)
Definition: JSONSerializer.h:588
VersionType version(VersionType version, const T *caller=NULL)
Definition: JSONSerializer.h:138
Stores meta information for each member.
Definition: ReflectMemberMeta.h:64
std::vector< void *> ObjectsVector
Definition: Deserializer.h:311
void pointerWithClassType(const std::string &type)
Definition: JSONSerializer.h:272
Definition: StlCollections.h:339
void property(const char *name, T &member, const char *comment, PropertyHint &&hint=PropertyHint(), ReflectCtrlFlags flags=REFLECT_CTRLFLAG_NONE)
Definition: RecursiveMemberReflector.h:985
std::map< std::string, void *> ObjectNameToInstanceMap
Definition: Deserializer.h:307
void collection(T &member)
Definition: JSONSerializer.h:247
void serialize(const std::string &name, const T &value, const std::string &comment="")
Serializes the specified object value under the given name.
Definition: Serializer.h:204
MIRA_DEPRECATED("Please call as version<MyType>(v) or version(v, this)", VersionType version(VersionType expectedVersion))
Definition: JSONSerializer.h:471
void invokeMemberOverwrite(T &member, const ReflectMemberMeta &meta)
Definition: JSONSerializer.h:753
static void reflect(JSONDeserializer &r, uint32 &ioCount)
Definition: JSONSerializer.h:893
#define MIRA_THROW(ex, msg)
Macro for throwing an exception.
Definition: Exception.h:78
A property hint gives optional instructions to the property editor, i.e.
Definition: PropertyHint.h:82
const json::Value * getMember(const json::Value *value, const std::string &name)
Definition: JSONSerializer.h:440
VersionType version(VersionType expectedVersion, const T *object=NULL)
Definition: JSONSerializer.h:461
MapType< std::string, mapped_type > Container
Definition: JSONSerializer.h:954
const ReflectMemberMeta & getCurrentMemberMeta() const
Returns the meta-information of the current member that is reflected.
Definition: RecursiveMemberReflector.h:479
uint32 getStringMapElementCount()
Definition: JSONSerializer.h:774
MIRA_ENUM_TO_FLAGS_INCLASS(OutputFormat) JSONSerializer(bool readOnly
Construct a serializer.
void object(T &member)
Definition: JSONSerializer.h:211
Deserializer for serializing objects from JSON format.
Definition: JSONSerializer.h:401
void roproperty(const char *name, const std::string &id, const T &member, const char *comment, PropertyHint &&hint=PropertyHint(), ReflectCtrlFlags flags=REFLECT_CTRLFLAG_NONE)
Definition: JSONSerializer.h:299
ObjectNameToInstanceMap mObjectNameToInstance
maps full id names to instance pointers
Definition: Deserializer.h:309
VersionType version(VersionType version, AcceptDesiredVersion, const T *caller=NULL)
Definition: JSONSerializer.h:150
No flags.
Definition: ReflectControlFlags.h:65
PropertyHint type(const std::string &t)
Sets the attribute "type" to the specified value.
Definition: PropertyHint.h:295
Contains base class for all deserializers.
std::enable_if_t< std::is_same_v< T, typename MapType< std::string, T >::mapped_type >, void > collection(MapType< std::string, T > &member)
Definition: JSONSerializer.h:254
ObjectsVector mObjects
maps the ids to the instance pointers
Definition: Deserializer.h:313
void atomic(T &member)
Definition: JSONSerializer.h:506
static void reflect(JSONDeserializer &r, uint32 &ioCount)
Definition: JSONSerializer.h:879
Getter< T > getter(T(*f)())
Creates a Getter for global or static class methods returning the result by value.
Definition: GetterSetter.h:136
void atomic(json::Value &member)
Definition: JSONSerializer.h:194
json_spirit::mObject Object
A representation of an object (class, struct) in JSON.
Definition: JSON.h:181
void mapEntry(int id, const typename Container::value_type &p)
Definition: JSONSerializer.h:321
Base class for exceptions.
Definition: Exception.h:195
MapType< std::string, mapped_type > Container
Definition: JSONSerializer.h:936
Base::VersionType VersionType
Definition: Serializer.h:154
MIRA_ENUM_TO_FLAGS_INCLASS(InputFormat) JSONDeserializer(const json
Definition: JSONSerializer.h:420
json_spirit::mValue Value
A value is an abstract description of data in JSON (underlying data can either be one of the JSON bas...
Definition: JSON.h:174
typename ReflectorInterface< JSONSerializer >::VersionType VersionType
Definition: AbstractReflector.h:165
void deserialize(json::Value &value)
Definition: JSONSerializer.h:435
Accept associative containers with string keys as JSON object (keys = member names), in ADDITION to the standard array format (i.e.
Definition: JSONSerializer.h:417
VersionType version(VersionType expectedVersion, AcceptDesiredVersion, const T *caller=NULL)
Definition: JSONSerializer.h:478
static int forcedSerializeVersion()
Returns either the version number from value of environment variable &#39;MIRA_FORCE_SERIALIZE_VERSION&#39;, or -1 (= do not force a version).
Definition: Serializer.h:145
MIRA_DEPRECATED("Please call as version<MyType>(v) or version(v, this)", VersionType version(VersionType version))
Definition: JSONSerializer.h:143
Can be specialized for a concrete derived RecursiveMemberReflector to reflect the size of collections...
Definition: ReflectCollection.h:69
Holds a boost::function object to a special getter function that must meet the signature "T method()"...
Definition: GetterSetter.h:87
Definition: LoggingCore.h:76
void object(T &member)
Definition: JSONSerializer.h:561
const json::Value * getItem(const json::Value *value, std::size_t index)
Definition: JSONSerializer.h:449
static constexpr auto MIRA_REFLECTOR_TOPLEVEL_NAME
Use this when a reflector needs to choose a name for serializing an object.
Definition: RecursiveMemberReflector.h:269
void invokeMemberOverwrite(T &member, const ReflectMemberMeta &meta)
The actual invokeMember implementation that is called from invokeMember().
Definition: RecursiveMemberReflector.h:686
Default format.
Definition: JSONSerializer.h:102
ReflectCtrlFlags
Control Flags that can modify the behavior of certain reflectors.
Definition: ReflectControlFlags.h:63
"Null-Setter" tag-class where the AccessorSetterPart does nothing.
Definition: Accessor.h:198
OutputFormat
Flags for JSON output format.
Definition: JSONSerializer.h:99
Definition: LoggingCore.h:78
const json::Array * getCollection()
Definition: JSONSerializer.h:655
Default format.
Definition: JSONSerializer.h:411
Wrappers for JSON.
Accessor< Getter, Setter > makeAccessor(const Getter &getter, const Setter &setter)
Helper method that creates an accessor from a different combination of either direct access to a vari...
Definition: Accessor.h:300
Serialize associative containers with string keys as JSON object (keys = member names) ...
Definition: JSONSerializer.h:105
const char * id
The id (used for containers where the name is identical, in all other cases the id usually is equal t...
Definition: ReflectMemberMeta.h:73
void atomic(T &member)
Definition: JSONSerializer.h:178
static void reflect(JSONSerializer &r, Container &c)
Definition: JSONSerializer.h:939
Helpers for serialization and deserialization of STL containers.
Definition: StlCollections.h:391
std::string pointerClassType()
Definition: JSONSerializer.h:707
static void reflect(JSONSerializer &r, uint32 &ioCount)
Definition: JSONSerializer.h:864
void pointerReference(int referencedObjectID)
Definition: JSONSerializer.h:262
Is a special reflector that is used for deserialization.
Definition: Deserializer.h:99
OutputFormat format
Definition: JSONSerializer.h:115