cereal
A C++11 library for serialization
json.hpp
Go to the documentation of this file.
1 
3 /*
4  Copyright (c) 2014, Randolph Voorhies, Shane Grant
5  All rights reserved.
6 
7  Redistribution and use in source and binary forms, with or without
8  modification, are permitted provided that the following conditions are met:
9  * Redistributions of source code must retain the above copyright
10  notice, this list of conditions and the following disclaimer.
11  * Redistributions in binary form must reproduce the above copyright
12  notice, this list of conditions and the following disclaimer in the
13  documentation and/or other materials provided with the distribution.
14  * Neither the name of cereal nor the
15  names of its contributors may be used to endorse or promote products
16  derived from this software without specific prior written permission.
17 
18  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21  DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
22  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29 #ifndef CEREAL_ARCHIVES_JSON_HPP_
30 #define CEREAL_ARCHIVES_JSON_HPP_
31 
32 #include <cereal/cereal.hpp>
33 #include <cereal/details/util.hpp>
34 
35 namespace cereal
36 {
38 
40  { RapidJSONException( const char * what_ ) : Exception( what_ ) {} };
41 }
42 
43 // Override rapidjson assertions to throw exceptions by default
44 #ifndef CEREAL_RAPIDJSON_ASSERT
45 #define CEREAL_RAPIDJSON_ASSERT(x) if(!(x)){ \
46  throw ::cereal::RapidJSONException("rapidjson internal assertion failure: " #x); }
47 #endif // RAPIDJSON_ASSERT
48 
49 // Enable support for parsing of nan, inf, -inf
50 #define CEREAL_RAPIDJSON_WRITE_DEFAULT_FLAGS kWriteNanAndInfFlag
51 #define CEREAL_RAPIDJSON_PARSE_DEFAULT_FLAGS kParseFullPrecisionFlag | kParseNanAndInfFlag
52 
53 #include <cereal/external/rapidjson/prettywriter.h>
54 #include <cereal/external/rapidjson/ostreamwrapper.h>
55 #include <cereal/external/rapidjson/istreamwrapper.h>
56 #include <cereal/external/rapidjson/document.h>
57 #include <cereal/external/base64.hpp>
58 
59 #include <limits>
60 #include <sstream>
61 #include <stack>
62 #include <vector>
63 #include <string>
64 
65 namespace cereal
66 {
67  // ######################################################################
69 
95  class JSONOutputArchive : public OutputArchive<JSONOutputArchive>, public traits::TextArchive
96  {
97  enum class NodeType { StartObject, InObject, StartArray, InArray };
98 
99  using WriteStream = rapidjson::OStreamWrapper;
100  using JSONWriter = rapidjson::PrettyWriter<WriteStream>;
101 
102  public:
105 
108  class Options
109  {
110  public:
112  static Options Default(){ return Options(); }
113 
115  static Options NoIndent(){ return Options( JSONWriter::kDefaultMaxDecimalPlaces, IndentChar::space, 0 ); }
116 
118  enum class IndentChar : char
119  {
120  space = ' ',
121  tab = '\t',
122  newline = '\n',
123  carriage_return = '\r'
124  };
125 
127 
131  explicit Options( int precision = JSONWriter::kDefaultMaxDecimalPlaces,
132  IndentChar indentChar = IndentChar::space,
133  unsigned int indentLength = 4 ) :
134  itsPrecision( precision ),
135  itsIndentChar( static_cast<char>(indentChar) ),
136  itsIndentLength( indentLength ) { }
137 
138  private:
139  friend class JSONOutputArchive;
140  int itsPrecision;
141  char itsIndentChar;
142  unsigned int itsIndentLength;
143  };
144 
146 
149  JSONOutputArchive(std::ostream & stream, Options const & options = Options::Default() ) :
151  itsWriteStream(stream),
152  itsWriter(itsWriteStream),
153  itsNextName(nullptr)
154  {
155  itsWriter.SetMaxDecimalPlaces( options.itsPrecision );
156  itsWriter.SetIndent( options.itsIndentChar, options.itsIndentLength );
157  itsNameCounter.push(0);
158  itsNodeStack.push(NodeType::StartObject);
159  }
160 
163  {
164  if (itsNodeStack.top() == NodeType::InObject)
165  itsWriter.EndObject();
166  else if (itsNodeStack.top() == NodeType::InArray)
167  itsWriter.EndArray();
168  }
169 
171 
173  void saveBinaryValue( const void * data, size_t size, const char * name = nullptr )
174  {
175  setNextName( name );
176  writeName();
177 
178  auto base64string = base64::encode( reinterpret_cast<const unsigned char *>( data ), size );
179  saveValue( base64string );
180  };
181 
183 
186 
189 
193  void startNode()
194  {
195  writeName();
196  itsNodeStack.push(NodeType::StartObject);
197  itsNameCounter.push(0);
198  }
199 
201  void finishNode()
202  {
203  // if we ended up serializing an empty object or array, writeName
204  // will never have been called - so start and then immediately end
205  // the object/array.
206  //
207  // We'll also end any object/arrays we happen to be in
208  switch(itsNodeStack.top())
209  {
210  case NodeType::StartArray:
211  itsWriter.StartArray();
212  case NodeType::InArray:
213  itsWriter.EndArray();
214  break;
215  case NodeType::StartObject:
216  itsWriter.StartObject();
217  case NodeType::InObject:
218  itsWriter.EndObject();
219  break;
220  }
221 
222  itsNodeStack.pop();
223  itsNameCounter.pop();
224  }
225 
227  void setNextName( const char * name )
228  {
229  itsNextName = name;
230  }
231 
233  void saveValue(bool b) { itsWriter.Bool(b); }
235  void saveValue(int i) { itsWriter.Int(i); }
237  void saveValue(unsigned u) { itsWriter.Uint(u); }
239  void saveValue(int64_t i64) { itsWriter.Int64(i64); }
241  void saveValue(uint64_t u64) { itsWriter.Uint64(u64); }
243  void saveValue(double d) { itsWriter.Double(d); }
245  void saveValue(std::string const & s) { itsWriter.String(s.c_str(), static_cast<rapidjson::SizeType>( s.size() )); }
247  void saveValue(char const * s) { itsWriter.String(s); }
249  void saveValue(std::nullptr_t) { itsWriter.Null(); }
250 
251  private:
252  // Some compilers/OS have difficulty disambiguating the above for various flavors of longs, so we provide
253  // special overloads to handle these cases.
254 
256  template <class T, traits::EnableIf<sizeof(T) == sizeof(std::int32_t),
257  std::is_signed<T>::value> = traits::sfinae> inline
258  void saveLong(T l){ saveValue( static_cast<std::int32_t>( l ) ); }
259 
261  template <class T, traits::EnableIf<sizeof(T) != sizeof(std::int32_t),
262  std::is_signed<T>::value> = traits::sfinae> inline
263  void saveLong(T l){ saveValue( static_cast<std::int64_t>( l ) ); }
264 
266  template <class T, traits::EnableIf<sizeof(T) == sizeof(std::int32_t),
267  std::is_unsigned<T>::value> = traits::sfinae> inline
268  void saveLong(T lu){ saveValue( static_cast<std::uint32_t>( lu ) ); }
269 
271  template <class T, traits::EnableIf<sizeof(T) != sizeof(std::int32_t),
272  std::is_unsigned<T>::value> = traits::sfinae> inline
273  void saveLong(T lu){ saveValue( static_cast<std::uint64_t>( lu ) ); }
274 
275  public:
276 #ifdef _MSC_VER
277  void saveValue( unsigned long lu ){ saveLong( lu ); };
279 #else // _MSC_VER
280  template <class T, traits::EnableIf<std::is_same<T, long>::value,
282  !std::is_same<T, std::int32_t>::value,
283  !std::is_same<T, std::int64_t>::value> = traits::sfinae> inline
284  void saveValue( T t ){ saveLong( t ); }
285 
287  template <class T, traits::EnableIf<std::is_same<T, unsigned long>::value,
288  !std::is_same<T, std::uint32_t>::value,
289  !std::is_same<T, std::uint64_t>::value> = traits::sfinae> inline
290  void saveValue( T t ){ saveLong( t ); }
291 #endif // _MSC_VER
292 
294 
295  template <class T, traits::EnableIf<std::is_arithmetic<T>::value,
296  !std::is_same<T, long>::value,
297  !std::is_same<T, unsigned long>::value,
298  !std::is_same<T, std::int64_t>::value,
299  !std::is_same<T, std::uint64_t>::value,
300  (sizeof(T) >= sizeof(long double) || sizeof(T) >= sizeof(long long))> = traits::sfinae> inline
301  void saveValue(T const & t)
302  {
303  std::stringstream ss; ss.precision( std::numeric_limits<long double>::max_digits10 );
304  ss << t;
305  saveValue( ss.str() );
306  }
307 
309 
321  void writeName()
322  {
323  NodeType const & nodeType = itsNodeStack.top();
324 
325  // Start up either an object or an array, depending on state
326  if(nodeType == NodeType::StartArray)
327  {
328  itsWriter.StartArray();
329  itsNodeStack.top() = NodeType::InArray;
330  }
331  else if(nodeType == NodeType::StartObject)
332  {
333  itsNodeStack.top() = NodeType::InObject;
334  itsWriter.StartObject();
335  }
336 
337  // Array types do not output names
338  if(nodeType == NodeType::InArray) return;
339 
340  if(itsNextName == nullptr)
341  {
342  std::string name = "value" + std::to_string( itsNameCounter.top()++ ) + "\0";
343  saveValue(name);
344  }
345  else
346  {
347  saveValue(itsNextName);
348  itsNextName = nullptr;
349  }
350  }
351 
353  void makeArray()
354  {
355  itsNodeStack.top() = NodeType::StartArray;
356  }
357 
359 
360  private:
361  WriteStream itsWriteStream;
362  JSONWriter itsWriter;
363  char const * itsNextName;
364  std::stack<uint32_t> itsNameCounter;
365  std::stack<NodeType> itsNodeStack;
366  }; // JSONOutputArchive
367 
368  // ######################################################################
370 
406  class JSONInputArchive : public InputArchive<JSONInputArchive>, public traits::TextArchive
407  {
408  private:
409  using ReadStream = rapidjson::IStreamWrapper;
410  typedef rapidjson::GenericValue<rapidjson::UTF8<>> JSONValue;
411  typedef JSONValue::ConstMemberIterator MemberIterator;
412  typedef JSONValue::ConstValueIterator ValueIterator;
413  typedef rapidjson::Document::GenericValue GenericValue;
414 
415  public:
418 
421 
422  JSONInputArchive(std::istream & stream) :
424  itsNextName( nullptr ),
425  itsReadStream(stream)
426  {
427  itsDocument.ParseStream<>(itsReadStream);
428  if (itsDocument.IsArray())
429  itsIteratorStack.emplace_back(itsDocument.Begin(), itsDocument.End());
430  else
431  itsIteratorStack.emplace_back(itsDocument.MemberBegin(), itsDocument.MemberEnd());
432  }
433 
434  ~JSONInputArchive() CEREAL_NOEXCEPT = default;
435 
437 
442  void loadBinaryValue( void * data, size_t size, const char * name = nullptr )
443  {
444  itsNextName = name;
445 
446  std::string encoded;
447  loadValue( encoded );
448  auto decoded = base64::decode( encoded );
449 
450  if( size != decoded.size() )
451  throw Exception("Decoded binary data size does not match specified size");
452 
453  std::memcpy( data, decoded.data(), decoded.size() );
454  itsNextName = nullptr;
455  };
456 
457  private:
459 
462 
465 
467  class Iterator
468  {
469  public:
470  Iterator() : itsIndex( 0 ), itsType(Null_) {}
471 
472  Iterator(MemberIterator begin, MemberIterator end) :
473  itsMemberItBegin(begin), itsMemberItEnd(end), itsIndex(0), itsType(Member)
474  { }
475 
476  Iterator(ValueIterator begin, ValueIterator end) :
477  itsValueItBegin(begin), itsValueItEnd(end), itsIndex(0), itsType(Value)
478  { }
479 
481  Iterator & operator++()
482  {
483  ++itsIndex;
484  return *this;
485  }
486 
488  GenericValue const & value()
489  {
490  switch(itsType)
491  {
492  case Value : return itsValueItBegin[itsIndex];
493  case Member: return itsMemberItBegin[itsIndex].value;
494  default: throw cereal::Exception("Invalid Iterator Type!");
495  }
496  }
497 
499  const char * name() const
500  {
501  if( itsType == Member && (itsMemberItBegin + itsIndex) != itsMemberItEnd )
502  return itsMemberItBegin[itsIndex].name.GetString();
503  else
504  return nullptr;
505  }
506 
508 
509  inline void search( const char * searchName )
510  {
511  const auto len = std::strlen( searchName );
512  size_t index = 0;
513  for( auto it = itsMemberItBegin; it != itsMemberItEnd; ++it, ++index )
514  {
515  const auto currentName = it->name.GetString();
516  if( ( std::strncmp( searchName, currentName, len ) == 0 ) &&
517  ( std::strlen( currentName ) == len ) )
518  {
519  itsIndex = index;
520  return;
521  }
522  }
523 
524  throw Exception("JSON Parsing failed - provided NVP (" + std::string(searchName) + ") not found");
525  }
526 
527  private:
528  MemberIterator itsMemberItBegin, itsMemberItEnd;
529  ValueIterator itsValueItBegin, itsValueItEnd;
530  size_t itsIndex;
531  enum Type {Value, Member, Null_} itsType;
532  };
533 
535 
543  inline void search()
544  {
545  // The name an NVP provided with setNextName()
546  if( itsNextName )
547  {
548  // The actual name of the current node
549  auto const actualName = itsIteratorStack.back().name();
550 
551  // Do a search if we don't see a name coming up, or if the names don't match
552  if( !actualName || std::strcmp( itsNextName, actualName ) != 0 )
553  itsIteratorStack.back().search( itsNextName );
554  }
555 
556  itsNextName = nullptr;
557  }
558 
559  public:
561 
570  void startNode()
571  {
572  search();
573 
574  if(itsIteratorStack.back().value().IsArray())
575  itsIteratorStack.emplace_back(itsIteratorStack.back().value().Begin(), itsIteratorStack.back().value().End());
576  else
577  itsIteratorStack.emplace_back(itsIteratorStack.back().value().MemberBegin(), itsIteratorStack.back().value().MemberEnd());
578  }
579 
581  void finishNode()
582  {
583  itsIteratorStack.pop_back();
584  ++itsIteratorStack.back();
585  }
586 
588 
589  const char * getNodeName() const
590  {
591  return itsIteratorStack.back().name();
592  }
593 
595  void setNextName( const char * name )
596  {
597  itsNextName = name;
598  }
599 
601  template <class T, traits::EnableIf<std::is_signed<T>::value,
602  sizeof(T) < sizeof(int64_t)> = traits::sfinae> inline
603  void loadValue(T & val)
604  {
605  search();
606 
607  val = static_cast<T>( itsIteratorStack.back().value().GetInt() );
608  ++itsIteratorStack.back();
609  }
610 
612  template <class T, traits::EnableIf<std::is_unsigned<T>::value,
613  sizeof(T) < sizeof(uint64_t),
614  !std::is_same<bool, T>::value> = traits::sfinae> inline
615  void loadValue(T & val)
616  {
617  search();
618 
619  val = static_cast<T>( itsIteratorStack.back().value().GetUint() );
620  ++itsIteratorStack.back();
621  }
622 
624  void loadValue(bool & val) { search(); val = itsIteratorStack.back().value().GetBool(); ++itsIteratorStack.back(); }
626  void loadValue(int64_t & val) { search(); val = itsIteratorStack.back().value().GetInt64(); ++itsIteratorStack.back(); }
628  void loadValue(uint64_t & val) { search(); val = itsIteratorStack.back().value().GetUint64(); ++itsIteratorStack.back(); }
630  void loadValue(float & val) { search(); val = static_cast<float>(itsIteratorStack.back().value().GetDouble()); ++itsIteratorStack.back(); }
632  void loadValue(double & val) { search(); val = itsIteratorStack.back().value().GetDouble(); ++itsIteratorStack.back(); }
634  void loadValue(std::string & val) { search(); val = itsIteratorStack.back().value().GetString(); ++itsIteratorStack.back(); }
636  void loadValue(std::nullptr_t&) { search(); CEREAL_RAPIDJSON_ASSERT(itsIteratorStack.back().value().IsNull()); ++itsIteratorStack.back(); }
637 
638  // Special cases to handle various flavors of long, which tend to conflict with
639  // the int32_t or int64_t on various compiler/OS combinations. MSVC doesn't need any of this.
640  #ifndef _MSC_VER
641  private:
643  template <class T> inline
644  typename std::enable_if<sizeof(T) == sizeof(std::int32_t) && std::is_signed<T>::value, void>::type
645  loadLong(T & l){ loadValue( reinterpret_cast<std::int32_t&>( l ) ); }
646 
648  template <class T> inline
649  typename std::enable_if<sizeof(T) == sizeof(std::int64_t) && std::is_signed<T>::value, void>::type
650  loadLong(T & l){ loadValue( reinterpret_cast<std::int64_t&>( l ) ); }
651 
653  template <class T> inline
654  typename std::enable_if<sizeof(T) == sizeof(std::uint32_t) && !std::is_signed<T>::value, void>::type
655  loadLong(T & lu){ loadValue( reinterpret_cast<std::uint32_t&>( lu ) ); }
656 
658  template <class T> inline
659  typename std::enable_if<sizeof(T) == sizeof(std::uint64_t) && !std::is_signed<T>::value, void>::type
660  loadLong(T & lu){ loadValue( reinterpret_cast<std::uint64_t&>( lu ) ); }
661 
662  public:
664  template <class T> inline
665  typename std::enable_if<std::is_same<T, long>::value &&
666  sizeof(T) >= sizeof(std::int64_t) &&
667  !std::is_same<T, std::int64_t>::value, void>::type
668  loadValue( T & t ){ loadLong(t); }
669 
671  template <class T> inline
672  typename std::enable_if<std::is_same<T, unsigned long>::value &&
673  sizeof(T) >= sizeof(std::uint64_t) &&
674  !std::is_same<T, std::uint64_t>::value, void>::type
675  loadValue( T & t ){ loadLong(t); }
676  #endif // _MSC_VER
677 
678  private:
680  void stringToNumber( std::string const & str, long long & val ) { val = std::stoll( str ); }
682  void stringToNumber( std::string const & str, unsigned long long & val ) { val = std::stoull( str ); }
684  void stringToNumber( std::string const & str, long double & val ) { val = std::stold( str ); }
685 
686  public:
688  template <class T, traits::EnableIf<std::is_arithmetic<T>::value,
689  !std::is_same<T, long>::value,
690  !std::is_same<T, unsigned long>::value,
691  !std::is_same<T, std::int64_t>::value,
692  !std::is_same<T, std::uint64_t>::value,
693  (sizeof(T) >= sizeof(long double) || sizeof(T) >= sizeof(long long))> = traits::sfinae>
694  inline void loadValue(T & val)
695  {
696  std::string encoded;
697  loadValue( encoded );
698  stringToNumber( encoded, val );
699  }
700 
702  void loadSize(size_type & size)
703  {
704  if (itsIteratorStack.size() == 1)
705  size = itsDocument.Size();
706  else
707  size = (itsIteratorStack.rbegin() + 1)->value().Size();
708  }
709 
711 
712  private:
713  const char * itsNextName;
714  ReadStream itsReadStream;
715  std::vector<Iterator> itsIteratorStack;
716  rapidjson::Document itsDocument;
717  };
718 
719  // ######################################################################
720  // JSONArchive prologue and epilogue functions
721  // ######################################################################
722 
723  // ######################################################################
725 
726  template <class T> inline
728  { }
729 
731  template <class T> inline
733  { }
734 
735  // ######################################################################
737 
738  template <class T> inline
740  { }
741 
743 
744  template <class T> inline
746  { }
747 
748  // ######################################################################
750 
752  template <class T> inline
753  void prologue( JSONOutputArchive & ar, SizeTag<T> const & )
754  {
755  ar.makeArray();
756  }
757 
759  template <class T> inline
761  { }
762 
763  // ######################################################################
765 
766  template <class T> inline
768  { }
769 
771  template <class T> inline
773  { }
774 
775  // ######################################################################
777 
781  template <class T, traits::EnableIf<!std::is_arithmetic<T>::value,
784  inline void prologue( JSONOutputArchive & ar, T const & )
785  {
786  ar.startNode();
787  }
788 
790  template <class T, traits::EnableIf<!std::is_arithmetic<T>::value,
793  inline void prologue( JSONInputArchive & ar, T const & )
794  {
795  ar.startNode();
796  }
797 
798  // ######################################################################
800 
803  template <class T, traits::EnableIf<!std::is_arithmetic<T>::value,
806  inline void epilogue( JSONOutputArchive & ar, T const & )
807  {
808  ar.finishNode();
809  }
810 
812  template <class T, traits::EnableIf<!std::is_arithmetic<T>::value,
815  inline void epilogue( JSONInputArchive & ar, T const & )
816  {
817  ar.finishNode();
818  }
819 
820  // ######################################################################
822  inline
823  void prologue( JSONOutputArchive & ar, std::nullptr_t const & )
824  {
825  ar.writeName();
826  }
827 
829  inline
830  void prologue( JSONInputArchive &, std::nullptr_t const & )
831  { }
832 
833  // ######################################################################
835  inline
836  void epilogue( JSONOutputArchive &, std::nullptr_t const & )
837  { }
838 
840  inline
841  void epilogue( JSONInputArchive &, std::nullptr_t const & )
842  { }
843 
844  // ######################################################################
846  template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline
847  void prologue( JSONOutputArchive & ar, T const & )
848  {
849  ar.writeName();
850  }
851 
853  template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline
854  void prologue( JSONInputArchive &, T const & )
855  { }
856 
857  // ######################################################################
859  template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline
860  void epilogue( JSONOutputArchive &, T const & )
861  { }
862 
864  template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline
865  void epilogue( JSONInputArchive &, T const & )
866  { }
867 
868  // ######################################################################
870  template<class CharT, class Traits, class Alloc> inline
871  void prologue(JSONOutputArchive & ar, std::basic_string<CharT, Traits, Alloc> const &)
872  {
873  ar.writeName();
874  }
875 
877  template<class CharT, class Traits, class Alloc> inline
878  void prologue(JSONInputArchive &, std::basic_string<CharT, Traits, Alloc> const &)
879  { }
880 
881  // ######################################################################
883  template<class CharT, class Traits, class Alloc> inline
884  void epilogue(JSONOutputArchive &, std::basic_string<CharT, Traits, Alloc> const &)
885  { }
886 
888  template<class CharT, class Traits, class Alloc> inline
889  void epilogue(JSONInputArchive &, std::basic_string<CharT, Traits, Alloc> const &)
890  { }
891 
892  // ######################################################################
893  // Common JSONArchive serialization functions
894  // ######################################################################
896  template <class T> inline
898  {
899  ar.setNextName( t.name );
900  ar( t.value );
901  }
902 
903  template <class T> inline
905  {
906  ar.setNextName( t.name );
907  ar( t.value );
908  }
909 
911  inline
912  void CEREAL_SAVE_FUNCTION_NAME(JSONOutputArchive & ar, std::nullptr_t const & t)
913  {
914  ar.saveValue( t );
915  }
916 
918  inline
919  void CEREAL_LOAD_FUNCTION_NAME(JSONInputArchive & ar, std::nullptr_t & t)
920  {
921  ar.loadValue( t );
922  }
923 
925  template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline
927  {
928  ar.saveValue( t );
929  }
930 
932  template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline
934  {
935  ar.loadValue( t );
936  }
937 
939  template<class CharT, class Traits, class Alloc> inline
940  void CEREAL_SAVE_FUNCTION_NAME(JSONOutputArchive & ar, std::basic_string<CharT, Traits, Alloc> const & str)
941  {
942  ar.saveValue( str );
943  }
944 
946  template<class CharT, class Traits, class Alloc> inline
947  void CEREAL_LOAD_FUNCTION_NAME(JSONInputArchive & ar, std::basic_string<CharT, Traits, Alloc> & str)
948  {
949  ar.loadValue( str );
950  }
951 
952  // ######################################################################
954  template <class T> inline
956  {
957  // nothing to do here, we don't explicitly save the size
958  }
959 
961  template <class T> inline
963  {
964  ar.loadSize( st.size );
965  }
966 } // namespace cereal
967 
968 // register archives for polymorphic support
971 
972 // tie input and output archives together
974 
975 #endif // CEREAL_ARCHIVES_JSON_HPP_
void saveValue(T t)
Serialize a long if it would not be caught otherwise.
Definition: json.hpp:284
static Options Default()
Default options.
Definition: json.hpp:112
void saveValue(int64_t i64)
Saves an int64 to the current node.
Definition: json.hpp:239
An exception thrown when rapidjson fails an internal assertion.
Definition: json.hpp:39
void startNode()
Starts a new node in the JSON output.
Definition: json.hpp:193
void saveValue(std::string const &s)
Saves a string to the current node.
Definition: json.hpp:245
#define CEREAL_SETUP_ARCHIVE_TRAITS(InputArchive, OutputArchive)
Sets up traits that relate an input archive to an output archive.
Definition: traits.hpp:169
void saveValue(uint64_t u64)
Saves a uint64 to the current node.
Definition: json.hpp:241
void saveValue(int i)
Saves an int to the current node.
Definition: json.hpp:235
A wrapper around size metadata.
Definition: helpers.hpp:271
void finishNode()
Designates the most recently added node as finished.
Definition: json.hpp:201
A class containing various advanced options for the JSON archive.
Definition: json.hpp:108
void prologue(JSONOutputArchive &, NameValuePair< T > const &)
Prologue for NVPs for JSON archives.
Definition: json.hpp:727
typename detail::EnableIfHelper< Conditions... >::type EnableIf
Provides a way to enable a function if conditions are met.
Definition: traits.hpp:116
void writeName()
Write the name of the upcoming node and prepare object/array state.
Definition: json.hpp:321
Checks to see if the base class used in a cast has a minimal serialization.
Definition: traits.hpp:1173
void saveValue(std::nullptr_t)
Saves a nullptr to the current node.
Definition: json.hpp:249
void saveValue(char const *s)
Saves a const char * to the current node.
Definition: json.hpp:247
void loadBinaryValue(void *data, size_t size, const char *name=nullptr)
Loads some binary data, encoded as a base64 string.
Definition: json.hpp:442
Options(int precision=JSONWriter::kDefaultMaxDecimalPlaces, IndentChar indentChar=IndentChar::space, unsigned int indentLength=4)
Specify specific options for the JSONOutputArchive.
Definition: json.hpp:131
Type traits only struct used to mark an archive as human readable (text based)
Definition: traits.hpp:1299
The base input archive class.
Definition: cereal.hpp:585
static Options NoIndent()
Default options with no indentation.
Definition: json.hpp:115
An output archive designed to save data to JSON.
Definition: json.hpp:95
void saveValue(double d)
Saves a double to the current node.
Definition: json.hpp:243
uint64_t size_type
The size type used by cereal.
Definition: helpers.hpp:59
Definition: access.hpp:40
An input archive designed to load data from JSON.
Definition: json.hpp:406
#define CEREAL_REGISTER_ARCHIVE(Archive)
Registers a specific Archive type with cereal.
Definition: cereal.hpp:141
void makeArray()
Designates that the current node should be output as an array, not an object.
Definition: json.hpp:353
void saveValue(T const &t)
Save exotic arithmetic as strings to current node.
Definition: json.hpp:301
Internal misc utilities.
Main cereal functionality.
~JSONOutputArchive() CEREAL_NOEXCEPT
Destructor, flushes the JSON.
Definition: json.hpp:162
For holding name value pairs.
Definition: helpers.hpp:135
#define CEREAL_LOAD_FUNCTION_NAME
The deserialization (load) function name to search for.
Definition: macros.hpp:71
JSONInputArchive(std::istream &stream)
Construct, reading from the provided stream.
Definition: json.hpp:422
void setNextName(const char *name)
Sets the name for the next node created with startNode.
Definition: json.hpp:227
#define CEREAL_NOEXCEPT
Defines the CEREAL_NOEXCEPT macro to use instead of noexcept.
Definition: macros.hpp:116
void saveValue(unsigned u)
Saves a uint to the current node.
Definition: json.hpp:237
void finishNode()
Finishes the most recently started node.
Definition: json.hpp:581
The base output archive class.
Definition: cereal.hpp:234
void saveValue(bool b)
Saves a bool to the current node.
Definition: json.hpp:233
IndentChar
The character to use for indenting.
Definition: json.hpp:118
#define CEREAL_SAVE_FUNCTION_NAME
The serialization (save) function name to search for.
Definition: macros.hpp:78
void saveBinaryValue(const void *data, size_t size, const char *name=nullptr)
Saves some binary data, encoded as a base64 string, with an optional name.
Definition: json.hpp:173
const char * getNodeName() const
Retrieves the current node name.
Definition: json.hpp:589
void loadSize(size_type &size)
Loads the size for a SizeTag.
Definition: json.hpp:702
void epilogue(JSONOutputArchive &, NameValuePair< T > const &)
Epilogue for NVPs for JSON archives.
Definition: json.hpp:739
void startNode()
Starts a new node, going into its proper iterator.
Definition: json.hpp:570
void loadValue(T &val)
Loads a value from the current node - long double and long long overloads.
Definition: json.hpp:694
JSONOutputArchive(std::ostream &stream, Options const &options=Options::Default())
Construct, outputting to the provided stream.
Definition: json.hpp:149
void setNextName(const char *name)
Sets the name for the next node created with startNode.
Definition: json.hpp:595
::type loadValue(T &t)
Loads a value from the current node - small signed overload.
Definition: json.hpp:675
An exception class thrown when things go wrong at runtime.
Definition: helpers.hpp:48