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 
67 
95 class JSONSerializer : public Serializer<JSONSerializer>
96 {
98 
99 public:
101 
102 public:
105  {
107  STANDARD = 0x00,
108 
111  };
112 
113  MIRA_ENUM_TO_FLAGS_INCLASS(OutputFormat) // generate logical operators for enum values
114 
115 
120  JSONSerializer(bool readOnly = false, OutputFormat format = STANDARD)
121  : mReadOnly(readOnly), mOutputFormat(format)
122  {}
123 
125  template<typename T>
126  json::Value serialize(const T& value)
127  {
128  mFirstComplex = true;
129  auto jvalue = json::Value();
130  mValuePtr = &jvalue;
132  return jvalue;
133  }
134 
135  json::Value serialize(const json::Value& value)
136  {
137  return value;
138  }
139 
141 
142  template<typename T>
143  VersionType version(VersionType version, const T* caller = NULL)
144  {
145  return this->version<T>(version, false);
146  }
147 
148  MIRA_DEPRECATED("Please call as version<MyType>(v) or version(v, this)",
150  {
151  return versionLegacy(version);
152  }
153 
154  template<typename T>
156  {
157  return this->version<T>(version, true);
158  }
159 
160 private:
161  template<typename T>
162  VersionType version(VersionType version, bool acceptDesiredVersion)
163  {
164  version = this->template queryDesiredClassVersion<T>(version, acceptDesiredVersion);
165 
166  int vf = this->forcedSerializeVersion();
167  if ((vf == 0) || (vf == 1))
168  return versionLegacy(version);
169 
170  static const std::string v = std::string("@version[") + typeName<T>() + "]";
171  mValuePtr->get_obj()[v] = json::Value(json::cast(version));
172  return version;
173  }
174 
175  VersionType versionLegacy(VersionType version)
176  {
177  mValuePtr->get_obj()["@version"] = json::Value(json::cast((int)version));
178  return version;
179  }
180 
181 public:
182  template<typename T>
183  void atomic(T& member)
184  {
185  // member of a currently serialized object -> add member
186  if (mValuePtr->type() == json_spirit::obj_type) {
187  mValuePtr->get_obj()[getCurrentMemberMeta().id] = json::Value(json::cast(member));
188  }
189  // item of a currently serialized array -> add item
190  else if (mValuePtr->type() == json_spirit::array_type) {
191  mValuePtr->get_array().push_back(json::Value(json::cast(member)));
192  }
193  // no currently serialized value -> set member as new value
194  else {
195  *mValuePtr = json::Value(json::cast(member));
196  }
197  }
198 
200  {
201  // member of a currently serialized object -> add member
202  if (mValuePtr->type() == json_spirit::obj_type) {
203  mValuePtr->get_obj()[getCurrentMemberMeta().id] = member;
204  }
205  // item of a currently serialized array -> add item
206  else if (mValuePtr->type() == json_spirit::array_type) {
207  mValuePtr->get_array().push_back(member);
208  }
209  // no currently serialized value -> set member as new value
210  else {
211  *mValuePtr = member;
212  }
213  }
214 
215  template<typename T>
216  void object(T& member)
217  {
218  // in json the outer most object (the root object) has no name
219  if (mFirstComplex) {
220  *mValuePtr = json::Object();
221  mFirstComplex = false;
222  if (!mPointerClass.empty()) {
223  mValuePtr->get_obj()["@class"] = json::Value(mPointerClass);
224  mPointerClass.clear();
225  }
227  }
228  else {
229  json::Value* oldValue = mValuePtr;
230 
231  if (oldValue->type() == json_spirit::obj_type) {
232  json::Value& entry = oldValue->get_obj()[getCurrentMemberMeta().id];
233  entry = json::Object();
234  mValuePtr = &entry;
235  }
236  else if (oldValue->type() == json_spirit::array_type) {
237  oldValue->get_array().push_back(json::Object());
238  json::Value& entry = oldValue->get_array().back();
239  mValuePtr = &entry;
240  }
241 
242  if (!mPointerClass.empty()) {
243  mValuePtr->get_obj()["@class"] = json::Value(mPointerClass);
244  mPointerClass.clear();
245  }
247  mValuePtr = oldValue;
248  }
249  }
250 
251  template<typename T>
253  {
254  collectionInternal(member);
255  }
256 
257  template<template<typename U, typename V> class MapType, typename T>
258  typename std::enable_if_t<std::is_same_v<T, typename MapType<std::string, T>::mapped_type>,
259  void> collection(MapType<std::string, T>& member)
260  {
261  if (mOutputFormat & STRING_MAP_AS_OBJECT)
262  object(member);
263  else
264  collectionInternal(member);
265  }
266 
267  void pointerReference(int referencedObjectID)
268  {
269  json::Value val = json::Object();
270  val.get_obj()["@ref"] = json::Value(this->getHumanReadableFullID(referencedObjectID));
271  if (mValuePtr->type() == json_spirit::obj_type)
272  mValuePtr->get_obj()[getCurrentMemberMeta().id] = val;
273  else if (mValuePtr->type() == json_spirit::array_type)
274  mValuePtr->get_array().push_back(val);
275  }
276 
277  void pointerWithClassType(const std::string& type)
278  {
279  mPointerClass = type;
280  }
281 
282  void pointerNull()
283  {
284  if (mValuePtr->type() == json_spirit::obj_type)
285  mValuePtr->get_obj()[getCurrentMemberMeta().id] = json::Value();
286  else if (mValuePtr->type() == json_spirit::array_type)
287  mValuePtr->get_array().push_back(json::Value());
288  else
289  *mValuePtr = json::Value();
290  }
291 
292  template<typename T>
293  void roproperty(const char* name, const T& member, const char* comment,
295  {
296  if (!mReadOnly)
297  return;
298  // cast away constness, this is okay, since read only properties we
299  // will never write to the data
300  property(name, const_cast<T&>(member), comment, std::move(hint), flags);
301  }
302 
303  template<typename T>
304  void roproperty(const char* name, const std::string& id, const T& member, const char* comment,
306  {
307  if (!mReadOnly)
308  return;
309  // cast away constness, this is okay, since read only properties we
310  // will never write to the data
311  property(name, id, const_cast<T&>(member), comment, std::move(hint), flags);
312  }
313 
314  template<typename T>
315  void roproperty(const char* name, Getter<T> getter, const char* comment,
317  {
318  if (!mReadOnly)
319  return;
320  auto a = makeAccessor(getter, NullSetter<T>());
321  property(name, a, comment, std::move(hint), flags);
322  }
323 
324 public:
325  template<typename Container>
326  void mapEntry(int id, const typename Container::value_type& p)
327  {
328  using type = typename Container::mapped_type;
329 
330  if (mOutputFormat & STRING_MAP_AS_OBJECT) {
331  type& nonconstv = const_cast<type&>(p.second);
332  member(p.first.c_str(), nonconstv, "");
333  }
334  else {
335  serialization::reflectReadMapPair<JSONSerializer, Container>(*this, "item", id, p);
336  }
337  }
338 
339 private:
340  template<typename T>
341  void collectionInternal(T& member)
342  {
343  if (mFirstComplex) {
344  *mValuePtr = json::Array{};
345  mFirstComplex = false;
347  }
348  else {
349  json::Value* oldValue = mValuePtr;
350 
351  if (oldValue->type() == json_spirit::obj_type) {
352  json::Value& entry = oldValue->get_obj()[getCurrentMemberMeta().id];
353  entry = json::Array{};
354  mValuePtr = &entry;
355  }
356  else if (oldValue->type() == json_spirit::array_type) {
357  oldValue->get_array().push_back(json::Array{});
358  json::Value& entry = oldValue->get_array().back();
359  mValuePtr = &entry;
360  }
361  // serialize to adress of mValuePtr
363  mValuePtr = oldValue;
364  }
365  }
366 
367 private:
368  bool mFirstComplex;
369  bool mReadOnly;
370  json::Value* mValuePtr;
371  std::string mPointerClass;
372 
373  OutputFormat mOutputFormat;
374 };
375 
377 
406 class JSONDeserializer : public Deserializer<JSONDeserializer>
407 {
409 
410 public:
412 
413 public:
414 
417  {
419  STANDARD = 0x00,
420 
426  };
427 
428  MIRA_ENUM_TO_FLAGS_INCLASS(InputFormat) // generate logical operators for enum values
429 
431  mValue(&value), mStringMapAsObject(false), mInputFormat(format)
432  {
433  }
434 
435  template <typename T>
436  void deserialize(T& value)
437  {
438  mIndex = 0;
439  mFirstComplex = true;
441  }
442 
444  {
445  value = *mValue;
446  }
447 
448  const json::Value* getMember(const json::Value* value, const std::string& name)
449  {
450  if (value->get_obj().count(name) == 0)
451  MIRA_THROW(XMemberNotFound, "Missing member '" << name
452  << "' (" << getCurrentMemberFullID()
453  << ") while deserializing object='" << json::write(*mValue));
454  return &value->get_obj().at(name);
455  }
456 
457  const json::Value* getItem(const json::Value* value, std::size_t index)
458  {
459  if (value->get_array().size() <= index)
460  MIRA_THROW(XMemberNotFound, "Missing item[" << index
461  << "] (" << getCurrentMemberFullID()
462  << ") while deserializing collection='" << json::write(*mValue));
463  return &value->get_array()[index];
464  }
465 
467 
468  template <typename T>
469  VersionType version(VersionType expectedVersion, const T* object = NULL)
470  {
471  int vf = this->forcedDeserializeVersion();
472  if ((vf == 0) || (vf == 1))
473  return versionLegacy(expectedVersion);
474 
475  static const std::string v = std::string("@version[") + typeName<T>() + "]";
476  return getVersion<T>(expectedVersion, v);
477  }
478 
479  MIRA_DEPRECATED("Please call as version<MyType>(v) or version(v, this)",
480  VersionType version(VersionType expectedVersion))
481  {
482  return versionLegacy(expectedVersion);
483  }
484 
485  template <typename T>
486  VersionType version(VersionType expectedVersion, AcceptDesiredVersion, const T* caller = NULL)
487  {
488  return this->version<T>(expectedVersion);
489  }
490 
491 private:
492 
493  VersionType versionLegacy(VersionType expectedVersion)
494  {
495  return getVersion<void>(expectedVersion, "@version");
496  }
497 
498  template <typename T>
499  VersionType getVersion(VersionType expectedVersion, const std::string& versionElement)
500  {
501  if (mValue->get_obj().count(versionElement) == 0)
502  return 0;
503  VersionType version = mValue->get_obj().at(versionElement).get_value<json::TypeTrait<int>::type >();
504  if (version > expectedVersion) {
505  MIRA_LOG(WARNING) << "Trying to deserialize JSON data of a newer version (" << (int)version <<
506  ") of type " << typeName<T>() << " into an older version (" << (int)expectedVersion << ").";
507  }
508  return version;
509  }
510 
511 public:
512 
513  template<typename T>
514  void atomic(T& member)
515  {
516  if ( mValue->type() == json_spirit::obj_type )
517  {
518  const json::Value* item = getMember(mValue, mCurrentMemberID);
519  try {
520  member = json::reverse_cast<T>(item->get_value<typename json::TypeTrait<T>::type >());
521  }
522  catch(std::exception& ex)
523  {
524  MIRA_THROW(XInvalidConfig, "Error deserializing member '" << mCurrentMemberID
525  << "' (" << getCurrentMemberFullID()
526  << ") from object='" << json::write(*mValue)
527  << "' as " << typeName<T>() << ": " << ex.what());
528  }
529  }
530  else if ( mValue->type() == json_spirit::array_type )
531  {
532  const json::Value* item = getItem(mValue, mIndex++);
533  try {
534  member = json::reverse_cast<T>(item->get_value<typename json::TypeTrait<T>::type >());
535  }
536  catch(std::exception& ex)
537  {
538  MIRA_THROW(XInvalidConfig, "Error deserializing item[" << mIndex-1
539  << "] (" << getCurrentMemberFullID()
540  << ") from collection='" << json::write(*mValue)
541  << "' as " << typeName<T>() << ": " << ex.what());
542  }
543  }
544  else
545  {
546  try
547  {
548  member = json::reverse_cast<T>(mValue->get_value<typename json::TypeTrait<T>::type>());
549  }
550  catch(std::exception& ex)
551  {
552  MIRA_THROW(XMemberNotFound, "Error deserializing atomic (" << getCurrentMemberFullID()
553  << ") with content='" << json::write(*mValue) << "' as " << typeName<T>() << ": " << ex.what());
554  }
555  }
556  }
557 
559  {
560  if ( mValue->type() == json_spirit::obj_type )
561  member = *getMember(mValue, mCurrentMemberID);
562  else if ( mValue->type() == json_spirit::array_type )
563  member = *getItem(mValue, mIndex++);
564  else
565  member = *mValue;
566  }
567 
568  template<typename T>
569  void object(T& member)
570  {
571  if ( mFirstComplex )
572  {
573  mFirstComplex = false;
575  return;
576  }
577  const json::Value* oldValue = mValue;
578  std::size_t oldIndex = mIndex;
579  if ( mValue->type() == json_spirit::obj_type )
580  {
581  mValue = getMember(mValue, mCurrentMemberID);
582  }
583  else if ( mValue->type() == json_spirit::array_type )
584  {
585  mValue = getItem(mValue, oldIndex);
586  mIndex = 0;
587  }
588 
590 
591  mValue = oldValue;
592  mIndex = oldIndex+1;
593  }
594 
595  template<typename T>
597  {
598  collectionInternal(member);
599  }
600 
601  template<template<typename U, typename V> class MapType, typename T>
602  typename std::enable_if_t<std::is_same_v<T, typename MapType<std::string, T>::mapped_type>,
603  void> collection(MapType<std::string, T>& member)
604  {
605  if (!(mInputFormat & ACCEPT_STRING_MAP_AS_OBJECT)) {
606  collectionInternal(member);
607  return;
608  }
609 
610  if (mStringMapAsObject) {
611  json::Object::const_iterator oldCurrentStringMapMember = mCurrentStringMapMember;
612  object(member);
613  mCurrentStringMapMember = oldCurrentStringMapMember;
614  return;
615  }
616 
617  assert(mStringMapAsObject == false);
618 
619  // backup deserializer state
620  const json::Value* oldValue = mValue;
621  std::size_t oldIndex = mIndex;
622  std::string memberID = mCurrentMemberID;
623  bool firstComplex = mFirstComplex;
624 
626  ObjectsVector trackingInstances = mObjects;
627 
628  try {
629  try {
630  collectionInternal(member);
631  }
632  catch (XInvalidConfig& ex) {
633  MIRA_LOG(DEBUG) << "Deserialize map<string, T> as array failed, try as object:" << std::endl;
634 
635  // reset deserializer state to state before calling collection(), and try again, calling object()
636  mObjectNameToInstance = trackingNames;
637  mObjects = trackingInstances;
638 
639  mValue = oldValue;
640  mIndex = oldIndex;
641  mCurrentMemberID = memberID;
642  mFirstComplex = firstComplex;
643 
644  MIRA_LOG(DEBUG) << json::write(*mValue) << std::endl;
645 
646  mStringMapAsObject = true;
647  object(member);
648  }
649  }
650  // make sure we get to reset mStringMapAsObject as final statement on our way "up"
651  catch(Exception& ex) {
652  mStringMapAsObject = false;
653  MIRA_RETHROW(ex, "While trying to deserialize MapType<string, T> as object.");
654  }
655  catch(...) {
656  mStringMapAsObject = false;
657  throw;
658  }
659 
660  mStringMapAsObject = false;
661  }
662 
664  {
665  const json::Array* array;
666  try
667  {
668  array = &mValue->get_array();
669  }
670  catch(std::exception& ex)
671  {
672  MIRA_THROW(XInvalidConfig, "Error deserializing collection (" << getCurrentMemberFullID()
673  << ") from json::Value='" << json::write(*mValue) << "': " << ex.what());
674  }
675  return array;
676  }
677 
678  template<typename T>
679  void pointer(T* &pointer)
680  {
681  const json::Value* value;
682  if ( mFirstComplex )
683  value = mValue;
684  else
685  {
686  if ( mValue->type() == json_spirit::obj_type )
687  value = getMember(mValue, mCurrentMemberID);
688  else if ( mValue->type() == json_spirit::array_type )
689  value = getItem(mValue, mIndex);
690  }
691 
692  std::size_t oldIndex = mIndex;
693 
694  // do we have a null pointer?
695  if(value->is_null()) {
696  pointer = NULL;
697  }
698  // do we have a reference?
699  else {
700  if (value->type() == json_spirit::obj_type) {
701  auto it = value->get_obj().find("@ref");
702  if(it!=value->get_obj().end()) {
703  // we have a reference, so resolve it
704  pointer = resolveReference<T>(it->second.get_value<std::string>());
705  } else {
706  // we have a "normal" pointer, so deserialize it
708  }
709  } else {
710  // we have a "normal" pointer, so deserialize it
712  }
713  }
714 
715  if (mValue->type() == json_spirit::array_type)
716  mIndex = oldIndex+1;
717  }
718 
719  std::string pointerClassType()
720  {
721  const json::Value* value;
722  if ( mFirstComplex )
723  value = mValue;
724  else
725  {
726  if ( mValue->type() == json_spirit::obj_type )
727  {
728  try
729  {
730  value = getMember(mValue, mCurrentMemberID);
731  }
732  catch(XMemberNotFound& ex)
733  {
734  MIRA_RETHROW(ex, "Error getting pointer class type of member '"
735  << mCurrentMemberID << "' (" << getCurrentMemberFullID()
736  << ") from object='" << json::write(*mValue)<< "'");
737  }
738  }
739  else if ( mValue->type() == json_spirit::array_type )
740  {
741  try
742  {
743  value = getItem(mValue, mIndex);
744  }
745  catch(XMemberNotFound& ex)
746  {
747  MIRA_RETHROW(ex, "Error getting pointer class type of item[" << mIndex
748  << "] (" << getCurrentMemberFullID()
749  << ") from collection='" << json::write(*mValue) << "'");
750  }
751  }
752  }
753  if(value->type() == json_spirit::obj_type)
754  {
755  auto it = value->get_obj().find("@class");
756  if(it!=value->get_obj().end())
757  return it->second.get_value<std::string>();
758  }
759  return "Unknown Class";
760  }
761 
762  // hijack the invokeOverwrite method for adding a starting and closing tag
763  // around the serialized data
764  template<typename T>
766  {
767  std::string oldID = mCurrentMemberID;
768  if(meta.id!=NULL)
769  mCurrentMemberID = meta.id;
770  try
771  {
773  }
774  catch(...)
775  {
776  if(meta.id!=NULL)
777  mCurrentMemberID = oldID;
778  throw;
779  }
780  if(meta.id!=NULL)
781  mCurrentMemberID = oldID;
782  }
783 
784 public:
785 
787  {
788  if (mStringMapAsObject) {
789  try {
790  const json::Object* o = &mValue->get_obj();
791  mCurrentStringMapMember = mValue->get_obj().begin();
792  return (uint32)o->size();
793  }
794  catch(std::exception& ex)
795  {
796  MIRA_THROW(XInvalidConfig, "Error counting object elements from json::Value='"
797  << json::write(*mValue) << "': " << ex.what());
798  }
799  } else {
800  const json::Array* a = getCollection();
801  return (uint32)a->size();
802  }
803  }
804 
805  template<typename Container>
806  void mapEntry(int id, Container& c, typename Container::iterator& hint)
807  {
808  typedef typename Container::value_type value_type;
809  typedef typename Container::mapped_type mapped_type;
810 
811  if (mStringMapAsObject) {
812  std::string key = mCurrentStringMapMember->first;
813  hint = c.insert(hint, value_type(key, mapped_type()));
814  property(key.c_str(), hint->second, "");
815  ++mCurrentStringMapMember;
816  } else {
817  serialization::reflectWriteMapPair(*this, "item", "key", id, c, hint);
818  }
819  }
820 
821 private:
822  template<typename T>
823  void collectionInternal(T& member)
824  {
825  if ( mFirstComplex )
826  {
827  mFirstComplex = false;
829  return;
830  }
831  const json::Value* oldValue = mValue;
832  std::size_t oldIndex = mIndex;
833  if ( mValue->type() == json_spirit::obj_type )
834  {
835  mValue = getMember(mValue, mCurrentMemberID);
836  mIndex = 0;
837  }
838  else if ( mValue->type() == json_spirit::array_type )
839  {
840  mValue = getItem(mValue, oldIndex);
841  mIndex = 0;
842  }
843 
845 
846  mValue = oldValue;
847  mIndex = oldIndex+1;
848  }
849 
850 private:
851  bool mFirstComplex;
852  std::size_t mIndex;
853  const json::Value* mValue;
854  std::string mCurrentMemberID;
855 
856  bool mStringMapAsObject;
857  json::Object::const_iterator mCurrentStringMapMember;
858 
859  InputFormat mInputFormat;
860 };
861 
862 namespace serialization { // our private namespace
863 
865 
873 template<typename Collection>
875 {
876  static void reflect(JSONSerializer& r, uint32& ioCount)
877  {
878  // do nothing
879  }
880 };
881 
888 template<typename Collection>
890 {
891  static void reflect(JSONDeserializer& r, uint32& ioCount)
892  {
893  const json::Array* a = r.getCollection();
894  ioCount = (uint32)a->size();
895  }
896 };
897 
898 namespace SpecializeForMapped_Type {
899 
901 
902 template<typename Collection, typename T, typename HasMappedType = std::true_type>
904 {
905  static void reflect(JSONDeserializer& r, uint32& ioCount)
906  {
907  const json::Array* a = r.getCollection();
908  ioCount = (uint32)a->size();
909  }
910 };
911 
912 // If Collection::mapped_type exists and equals T, this specialization 'overrides' the definition above.
913 // Otherwise, this just does not exist (if Collection::mapped_type cannot be resolved, SFINAE, no error),
914 // or will be ignored (unless the third template parameter is explicitly given, which we should not do).
915 template<typename Collection, typename T>
916 struct ReflectCollectionCount<Collection, T,
917  typename std::is_same<T, typename Collection::mapped_type>::type>
918 {
919  static void reflect(JSONDeserializer& r, uint32& ioCount)
920  {
921  ioCount = r.getStringMapElementCount();
922  }
923 };
924 
926 
927 }
928 
934 template<template<typename U, typename V> class MapType, typename T>
935 struct ReflectCollectionCount<JSONDeserializer, MapType<std::string, T>>
936  : public SpecializeForMapped_Type::ReflectCollectionCount<MapType<std::string, T>, T>
937 {
938 };
939 
940 // ReflectReadMapItems/ReflectWriteMapItems must be applicable to generic map types (with string key),
941 // but there is no need to explicitly check for the existence of mapped_type, since these are not
942 // applied based on the more general IsCollection type trait, but only for types which
943 // define it explicitly (like std::map and std::unordered_map).
944 
945 template<template<typename U, typename V> class MapType, typename mapped_type>
946 struct ReflectReadMapItems<JSONSerializer, MapType<std::string, mapped_type>>
947 {
948  typedef MapType<std::string, mapped_type> Container;
949  typedef typename Container::value_type value_type;
950 
951  static void reflect(JSONSerializer& r, Container& c)
952  {
953  // store each item
954  int id=0;
955  foreach(value_type& p, c)
956  {
957  r.mapEntry<Container>(id, p);
958  ++id;
959  }
960  }
961 };
962 
963 template<template<typename U, typename V> class MapType, typename mapped_type>
964 struct ReflectWriteMapItems<JSONDeserializer, MapType<std::string, mapped_type>>
965 {
966  typedef MapType<std::string, mapped_type> Container;
967  typedef typename Container::iterator iterator;
968 
969  static void reflect(JSONDeserializer& r, Container& c, uint32 count)
970  {
971  iterator hint = c.begin();
972 
973  // restore each item and insert into the map
974  for(uint32 id=0; id<count; ++id)
975  r.mapEntry<Container>(id, c, hint);
976  }
977 };
978 
980 
981 }
982 
984 
985 } // namespace
986 
987 #endif
Serializer for serializing objects in JSON format.
Definition: JSONSerializer.h:95
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:436
Base::VersionType VersionType
Definition: JSONSerializer.h:466
void object(T &member)
Is called for each complex object.
Definition: RecursiveMemberReflector.h:385
void pointer(T *&pointer)
Definition: JSONSerializer.h:679
InputFormat
Flags for JSON input format.
Definition: JSONSerializer.h:416
void pointerNull()
Definition: JSONSerializer.h:282
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:969
void roproperty(const char *name, const T &member, const char *comment, PropertyHint &&hint=PropertyHint(), ReflectCtrlFlags flags=REFLECT_CTRLFLAG_NONE)
Definition: JSONSerializer.h:293
void mapEntry(int id, Container &c, typename Container::iterator &hint)
Definition: JSONSerializer.h:806
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:315
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:603
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:554
void member(const char *name, T &member, const char *comment, ReflectCtrlFlags flags=REFLECT_CTRLFLAG_NONE)
Definition: RecursiveMemberReflector.h:947
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:558
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:596
VersionType version(VersionType version, const T *caller=NULL)
Definition: JSONSerializer.h:143
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:277
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:1049
std::map< std::string, void *> ObjectNameToInstanceMap
Definition: Deserializer.h:307
void collection(T &member)
Definition: JSONSerializer.h:252
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:479
void invokeMemberOverwrite(T &member, const ReflectMemberMeta &meta)
Definition: JSONSerializer.h:765
static void reflect(JSONDeserializer &r, uint32 &ioCount)
Definition: JSONSerializer.h:905
#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:448
VersionType version(VersionType expectedVersion, const T *object=NULL)
Definition: JSONSerializer.h:469
MapType< std::string, mapped_type > Container
Definition: JSONSerializer.h:966
const ReflectMemberMeta & getCurrentMemberMeta() const
Returns the meta-information of the current member that is reflected.
Definition: RecursiveMemberReflector.h:543
uint32 getStringMapElementCount()
Definition: JSONSerializer.h:786
MIRA_ENUM_TO_FLAGS_INCLASS(OutputFormat) JSONSerializer(bool readOnly
Construct a serializer.
void object(T &member)
Definition: JSONSerializer.h:216
Deserializer for serializing objects from JSON format.
Definition: JSONSerializer.h:406
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:304
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:155
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:259
ObjectsVector mObjects
maps the ids to the instance pointers
Definition: Deserializer.h:313
void atomic(T &member)
Definition: JSONSerializer.h:514
static void reflect(JSONDeserializer &r, uint32 &ioCount)
Definition: JSONSerializer.h:891
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:199
Definition: JSONSerializer.h:66
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:326
Base class for exceptions.
Definition: Exception.h:195
MapType< std::string, mapped_type > Container
Definition: JSONSerializer.h:948
Base::VersionType VersionType
Definition: Serializer.h:154
MIRA_ENUM_TO_FLAGS_INCLASS(InputFormat) JSONDeserializer(const json
Definition: JSONSerializer.h:428
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:443
Accept associative containers with string keys as JSON object (keys = member names), in ADDITION to the standard array format (i.e.
Definition: JSONSerializer.h:425
VersionType version(VersionType expectedVersion, AcceptDesiredVersion, const T *caller=NULL)
Definition: JSONSerializer.h:486
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:148
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:569
const json::Value * getItem(const json::Value *value, std::size_t index)
Definition: JSONSerializer.h:457
static constexpr auto MIRA_REFLECTOR_TOPLEVEL_NAME
Use this when a reflector needs to choose a name for serializing an object.
Definition: RecursiveMemberReflector.h:333
void invokeMemberOverwrite(T &member, const ReflectMemberMeta &meta)
The actual invokeMember implementation that is called from invokeMember().
Definition: RecursiveMemberReflector.h:750
Default format.
Definition: JSONSerializer.h:107
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:104
Definition: LoggingCore.h:78
const json::Array * getCollection()
Definition: JSONSerializer.h:663
Default format.
Definition: JSONSerializer.h:419
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:110
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:183
static void reflect(JSONSerializer &r, Container &c)
Definition: JSONSerializer.h:951
Helpers for serialization and deserialization of STL containers.
Definition: StlCollections.h:391
std::string pointerClassType()
Definition: JSONSerializer.h:719
static void reflect(JSONSerializer &r, uint32 &ioCount)
Definition: JSONSerializer.h:876
void pointerReference(int referencedObjectID)
Definition: JSONSerializer.h:267
Is a special reflector that is used for deserialization.
Definition: Deserializer.h:99
OutputFormat format
Definition: JSONSerializer.h:120