C++ Rest SDK
The C++ REST SDK is a Microsoft project for cloud-based client-server communication in native code using a modern asynchronous C++ API design. This project aims to help C++ developers connect to and interact with services.
json.h
1 /***
2 * ==++==
3 *
4 * Copyright (c) Microsoft Corporation. All rights reserved.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 * ==--==
17 * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
18 *
19 * HTTP Library: JSON parser and writer
20 *
21 * For the latest on this and related APIs, please see http://casablanca.codeplex.com.
22 *
23 * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
24 ****/
25 #pragma once
26 
27 #ifndef _CASA_JSON_H
28 #define _CASA_JSON_H
29 
30 #include <memory>
31 #include <string>
32 #include <sstream>
33 #include <vector>
34 #include <unordered_map>
35 #include <cstdint>
36 #include "cpprest/details/basic_types.h"
37 #include "cpprest/asyncrt_utils.h"
38 
39 namespace web
40 {
42 namespace json
43 {
44  // Various forward declarations.
45  namespace details
46  {
47  class _Value;
48  class _Number;
49  class _Null;
50  class _Boolean;
51  class _String;
52  class _Object;
53  class _Array;
54  template <typename CharType> class JSON_Parser;
55  }
56 
57  namespace details
58  {
59  extern bool g_keep_json_object_unsorted;
60  }
61 
68  void _ASYNCRTIMP __cdecl keep_object_element_order(bool keep_order);
69 
70 #ifdef _WIN32
71 #ifdef _DEBUG
72 #define ENABLE_JSON_VALUE_VISUALIZER
73 #endif
74 #endif
75 
76  class number;
77  class array;
78  class object;
79 
83  class value
84  {
85  public:
90  {
103  };
104 
108  _ASYNCRTIMP value();
109 
114  _ASYNCRTIMP value(int32_t value);
115 
120  _ASYNCRTIMP value(uint32_t value);
121 
126  _ASYNCRTIMP value(int64_t value);
127 
132  _ASYNCRTIMP value(uint64_t value);
133 
138  _ASYNCRTIMP value(double value);
139 
144  _ASYNCRTIMP explicit value(bool value);
145 
154  _ASYNCRTIMP explicit value(utility::string_t value);
155 
165  _ASYNCRTIMP explicit value(utility::string_t value, bool has_escape_chars);
166 
182  _ASYNCRTIMP explicit value(const utility::char_t* value);
183 
199  _ASYNCRTIMP explicit value(const utility::char_t* value, bool has_escape_chars);
200 
204  _ASYNCRTIMP value(const value &);
205 
209  _ASYNCRTIMP value(value &&) CPPREST_NOEXCEPT ;
210 
215  _ASYNCRTIMP value &operator=(const value &);
216 
221  _ASYNCRTIMP value &operator=(value &&) CPPREST_NOEXCEPT ;
222 
223  // Static factories
224 
229  static _ASYNCRTIMP value __cdecl null();
230 
236  static _ASYNCRTIMP value __cdecl number(double value);
237 
243  static _ASYNCRTIMP value __cdecl number(int32_t value);
244 
250  static _ASYNCRTIMP value __cdecl number(uint32_t value);
251 
257  static _ASYNCRTIMP value __cdecl number(int64_t value);
258 
264  static _ASYNCRTIMP value __cdecl number(uint64_t value);
265 
271  static _ASYNCRTIMP value __cdecl boolean(bool value);
272 
282  static _ASYNCRTIMP value __cdecl string(utility::string_t value);
283 
294  static _ASYNCRTIMP value __cdecl string(utility::string_t value, bool has_escape_chars);
295 
296 #ifdef _WIN32
297 private:
298  // Only used internally by JSON parser.
299  static _ASYNCRTIMP value __cdecl string(const std::string &value);
300 public:
301 #endif
302 
308  static _ASYNCRTIMP json::value __cdecl object(bool keep_order = false);
309 
316  static _ASYNCRTIMP json::value __cdecl object(std::vector<std::pair<::utility::string_t, value>> fields, bool keep_order = false);
317 
322  static _ASYNCRTIMP json::value __cdecl array();
323 
329  static _ASYNCRTIMP json::value __cdecl array(size_t size);
330 
336  static _ASYNCRTIMP json::value __cdecl array(std::vector<value> elements);
337 
342  _ASYNCRTIMP json::value::value_type type() const;
343 
348  bool is_null() const { return type() == Null; };
349 
354  bool is_number() const { return type() == Number; }
355 
364  _ASYNCRTIMP bool is_integer() const;
365 
374  _ASYNCRTIMP bool is_double() const;
375 
380  bool is_boolean() const { return type() == Boolean; }
381 
386  bool is_string() const { return type() == String; }
387 
392  bool is_array() const { return type() == Array; }
393 
398  bool is_object() const { return type() == Object; }
399 
404  size_t size() const;
405 
410  _ASYNCRTIMP static value __cdecl parse(const utility::string_t &value);
411 
418  _ASYNCRTIMP static value __cdecl parse(const utility::string_t &value, std::error_code &errorCode);
419 
424  _ASYNCRTIMP utility::string_t serialize() const;
425 
430  CASABLANCA_DEPRECATED("This API is deprecated and has been renamed to avoid confusion with as_string(), use ::web::json::value::serialize() instead.")
431  _ASYNCRTIMP utility::string_t to_string() const;
432 
438  _ASYNCRTIMP static value __cdecl parse(utility::istream_t &input);
439 
446  _ASYNCRTIMP static value __cdecl parse(utility::istream_t &input, std::error_code &errorCode);
447 
452  _ASYNCRTIMP void serialize(utility::ostream_t &stream) const;
453 
454 #ifdef _WIN32
455  _ASYNCRTIMP static value __cdecl parse(std::istream& stream);
460 
467  _ASYNCRTIMP static value __cdecl parse(std::istream& stream, std::error_code& error);
468 
473  _ASYNCRTIMP void serialize(std::ostream& stream) const;
474 #endif
475 
481  _ASYNCRTIMP double as_double() const;
482 
488  _ASYNCRTIMP int as_integer() const;
489 
495  _ASYNCRTIMP const json::number& as_number() const;
496 
501  _ASYNCRTIMP bool as_bool() const;
502 
508  _ASYNCRTIMP json::array& as_array();
509 
515  _ASYNCRTIMP const json::array& as_array() const;
516 
521  _ASYNCRTIMP json::object& as_object();
522 
527  _ASYNCRTIMP const json::object& as_object() const;
528 
533  _ASYNCRTIMP const utility::string_t& as_string() const;
534 
540  _ASYNCRTIMP bool operator==(const value& other) const;
541 
547  bool operator!=(const value& other) const
548  {
549  return !((*this) == other);
550  }
551 
557  bool has_field(const utility::string_t &key) const;
558 
564  CASABLANCA_DEPRECATED("This API is deprecated and will be removed in a future release, use json::value::at() instead.")
565  value get(const utility::string_t &key) const;
566 
571  _ASYNCRTIMP void erase(size_t index);
572 
577  _ASYNCRTIMP void erase(const utility::string_t &key);
578 
584  _ASYNCRTIMP json::value& at(size_t index);
585 
591  _ASYNCRTIMP const json::value& at(size_t index) const;
592 
598  _ASYNCRTIMP json::value& at(const utility::string_t& key);
599 
605  _ASYNCRTIMP const json::value& at(const utility::string_t& key) const;
606 
612  _ASYNCRTIMP value & operator [] (const utility::string_t &key);
613 
614 #ifdef _WIN32
615 private:
616  // Only used internally by JSON parser
617  _ASYNCRTIMP value & operator [] (const std::string &key)
618  {
619  // JSON object stores its field map as a unordered_map of string_t, so this conversion is hard to avoid
621  }
622 public:
623 #endif
624 
630  CASABLANCA_DEPRECATED("This API is deprecated and will be removed in a future release, use json::value::at() instead.")
631  value get(size_t index) const;
632 
638  _ASYNCRTIMP value & operator [] (size_t index);
639 
640  private:
641  friend class web::json::details::_Object;
642  friend class web::json::details::_Array;
643  template<typename CharType> friend class web::json::details::JSON_Parser;
644 
645 #ifdef _WIN32
646  _ASYNCRTIMP void format(std::basic_string<utf16char> &string) const;
651 #endif
652  _ASYNCRTIMP void format(std::basic_string<char>& string) const;
657 
658 #ifdef ENABLE_JSON_VALUE_VISUALIZER
659  explicit value(std::unique_ptr<details::_Value> v, value_type kind) : m_value(std::move(v)), m_kind(kind)
660 #else
661  explicit value(std::unique_ptr<details::_Value> v) : m_value(std::move(v))
662 #endif
663  {}
664 
665  std::unique_ptr<details::_Value> m_value;
666 #ifdef ENABLE_JSON_VALUE_VISUALIZER
667  value_type m_kind;
668 #endif
669  };
670 
675  class json_exception : public std::exception
676  {
677  private:
678  std::string _message;
679  public:
680  json_exception(const utility::char_t * const &message) : _message(utility::conversions::to_utf8string(message)) { }
681 
682  // Must be narrow string because it derives from std::exception
683  const char* what() const CPPREST_NOEXCEPT
684  {
685  return _message.c_str();
686  }
687  };
688 
689  namespace details
690  {
691  enum json_error
692  {
693  left_over_character_in_stream = 1,
694  malformed_array_literal,
695  malformed_comment,
696  malformed_literal,
697  malformed_object_literal,
698  malformed_numeric_literal,
699  malformed_string_literal,
700  malformed_token,
701  mismatched_brances,
702  nesting,
703  unexpected_token
704  };
705 
706  class json_error_category_impl : public std::error_category
707  {
708  public:
709  virtual const char* name() const CPPREST_NOEXCEPT override
710  {
711  return "json";
712  }
713 
714  virtual std::string message(int ev) const override
715  {
716  switch (ev)
717  {
718  case json_error::left_over_character_in_stream:
719  return "Left-over characters in stream after parsing a JSON value";
720  case json_error::malformed_array_literal:
721  return "Malformed array literal";
722  case json_error::malformed_comment:
723  return "Malformed comment";
724  case json_error::malformed_literal:
725  return "Malformed literal";
726  case json_error::malformed_object_literal:
727  return "Malformed object literal";
728  case json_error::malformed_numeric_literal:
729  return "Malformed numeric literal";
730  case json_error::malformed_string_literal:
731  return "Malformed string literal";
732  case json_error::malformed_token:
733  return "Malformed token";
734  case json_error::mismatched_brances:
735  return "Mismatched braces";
736  case json_error::nesting:
737  return "Nesting too deep";
738  case json_error::unexpected_token:
739  return "Unexpected token";
740  default:
741  return "Unknown json error";
742  }
743  }
744  };
745 
746  const json_error_category_impl& json_error_category();
747  }
748 
752  class array
753  {
754  typedef std::vector<json::value> storage_type;
755 
756  public:
757  typedef storage_type::iterator iterator;
758  typedef storage_type::const_iterator const_iterator;
759  typedef storage_type::reverse_iterator reverse_iterator;
760  typedef storage_type::const_reverse_iterator const_reverse_iterator;
761  typedef storage_type::size_type size_type;
762 
763  private:
764  array() : m_elements() { }
765  array(size_type size) : m_elements(size) { }
766  array(storage_type elements) : m_elements(std::move(elements)) { }
767 
768  public:
773  iterator begin()
774  {
775  return m_elements.begin();
776  }
777 
782  const_iterator begin() const
783  {
784  return m_elements.cbegin();
785  }
786 
791  iterator end()
792  {
793  return m_elements.end();
794  }
795 
800  const_iterator end() const
801  {
802  return m_elements.cend();
803  }
804 
809  reverse_iterator rbegin()
810  {
811  return m_elements.rbegin();
812  }
813 
818  const_reverse_iterator rbegin() const
819  {
820  return m_elements.rbegin();
821  }
822 
827  reverse_iterator rend()
828  {
829  return m_elements.rend();
830  }
831 
836  const_reverse_iterator rend() const
837  {
838  return m_elements.crend();
839  }
840 
845  const_iterator cbegin() const
846  {
847  return m_elements.cbegin();
848  }
849 
854  const_iterator cend() const
855  {
856  return m_elements.cend();
857  }
858 
863  const_reverse_iterator crbegin() const
864  {
865  return m_elements.crbegin();
866  }
867 
872  const_reverse_iterator crend() const
873  {
874  return m_elements.crend();
875  }
876 
883  iterator erase(iterator position)
884  {
885  return m_elements.erase(position);
886  }
887 
892  void erase(size_type index)
893  {
894  if (index >= m_elements.size())
895  {
896  throw json_exception(_XPLATSTR("index out of bounds"));
897  }
898  m_elements.erase(m_elements.begin() + index);
899  }
900 
906  json::value& at(size_type index)
907  {
908  if (index >= m_elements.size())
909  throw json_exception(_XPLATSTR("index out of bounds"));
910 
911  return m_elements[index];
912  }
913 
919  const json::value& at(size_type index) const
920  {
921  if (index >= m_elements.size())
922  throw json_exception(_XPLATSTR("index out of bounds"));
923 
924  return m_elements[index];
925  }
926 
932  json::value& operator[](size_type index)
933  {
934  msl::safeint3::SafeInt<size_type> nMinSize(index);
935  nMinSize += 1;
936  msl::safeint3::SafeInt<size_type> nlastSize(m_elements.size());
937  if (nlastSize < nMinSize)
938  m_elements.resize(nMinSize);
939 
940  return m_elements[index];
941  }
942 
947  size_type size() const
948  {
949  return m_elements.size();
950  }
951 
952  private:
953  storage_type m_elements;
954 
955  friend class details::_Array;
956  template<typename CharType> friend class json::details::JSON_Parser;
957  };
958 
962  class object
963  {
964  typedef std::vector<std::pair<utility::string_t, json::value>> storage_type;
965 
966  public:
967  typedef storage_type::iterator iterator;
968  typedef storage_type::const_iterator const_iterator;
969  typedef storage_type::reverse_iterator reverse_iterator;
970  typedef storage_type::const_reverse_iterator const_reverse_iterator;
971  typedef storage_type::size_type size_type;
972 
973  private:
974  object(bool keep_order = false) : m_elements(), m_keep_order(keep_order) { }
975  object(storage_type elements, bool keep_order = false) : m_elements(std::move(elements)), m_keep_order(keep_order)
976  {
977  if (!keep_order) {
978  sort(m_elements.begin(), m_elements.end(), compare_pairs);
979  }
980  }
981 
982  public:
987  iterator begin()
988  {
989  return m_elements.begin();
990  }
991 
996  const_iterator begin() const
997  {
998  return m_elements.cbegin();
999  }
1000 
1005  iterator end()
1006  {
1007  return m_elements.end();
1008  }
1009 
1014  const_iterator end() const
1015  {
1016  return m_elements.cend();
1017  }
1018 
1023  reverse_iterator rbegin()
1024  {
1025  return m_elements.rbegin();
1026  }
1027 
1032  const_reverse_iterator rbegin() const
1033  {
1034  return m_elements.rbegin();
1035  }
1036 
1041  reverse_iterator rend()
1042  {
1043  return m_elements.rend();
1044  }
1045 
1050  const_reverse_iterator rend() const
1051  {
1052  return m_elements.crend();
1053  }
1054 
1059  const_iterator cbegin() const
1060  {
1061  return m_elements.cbegin();
1062  }
1063 
1068  const_iterator cend() const
1069  {
1070  return m_elements.cend();
1071  }
1072 
1077  const_reverse_iterator crbegin() const
1078  {
1079  return m_elements.crbegin();
1080  }
1081 
1086  const_reverse_iterator crend() const
1087  {
1088  return m_elements.crend();
1089  }
1090 
1097  iterator erase(iterator position)
1098  {
1099  return m_elements.erase(position);
1100  }
1101 
1106  void erase(const utility::string_t &key)
1107  {
1108  auto iter = find_by_key(key);
1109  if (iter == m_elements.end())
1110  {
1111  throw web::json::json_exception(_XPLATSTR("Key not found"));
1112  }
1113 
1114  m_elements.erase(iter);
1115  }
1116 
1122  json::value& at(const utility::string_t& key)
1123  {
1124  auto iter = find_by_key(key);
1125  if (iter == m_elements.end())
1126  {
1127  throw web::json::json_exception(_XPLATSTR("Key not found"));
1128  }
1129 
1130  return iter->second;
1131  }
1132 
1138  const json::value& at(const utility::string_t& key) const
1139  {
1140  auto iter = find_by_key(key);
1141  if (iter == m_elements.end())
1142  {
1143  throw web::json::json_exception(_XPLATSTR("Key not found"));
1144  }
1145 
1146  return iter->second;
1147  }
1148 
1154  json::value& operator[](const utility::string_t& key)
1155  {
1156  auto iter = find_insert_location(key);
1157 
1158  if (iter == m_elements.end() || key != iter->first)
1159  {
1160  return m_elements.insert(iter, std::pair<utility::string_t, value>(key, value()))->second;
1161  }
1162 
1163  return iter->second;
1164  }
1165 
1171  const_iterator find(const utility::string_t& key) const
1172  {
1173  return find_by_key(key);
1174  }
1175 
1180  size_type size() const
1181  {
1182  return m_elements.size();
1183  }
1184 
1189  bool empty() const
1190  {
1191  return m_elements.empty();
1192  }
1193  private:
1194 
1195  static bool compare_pairs(const std::pair<utility::string_t, value>& p1, const std::pair<utility::string_t, value>& p2)
1196  {
1197  return p1.first < p2.first;
1198  }
1199  static bool compare_with_key(const std::pair<utility::string_t, value>& p1, const utility::string_t& key)
1200  {
1201  return p1.first < key;
1202  }
1203 
1204  storage_type::iterator find_insert_location(const utility::string_t &key)
1205  {
1206  if (m_keep_order)
1207  {
1208  return std::find_if(m_elements.begin(), m_elements.end(),
1209  [&key](const std::pair<utility::string_t, value>& p) {
1210  return p.first == key;
1211  });
1212  }
1213  else
1214  {
1215  return std::lower_bound(m_elements.begin(), m_elements.end(), key, compare_with_key);
1216  }
1217  }
1218 
1219  storage_type::const_iterator find_by_key(const utility::string_t& key) const
1220  {
1221  if (m_keep_order)
1222  {
1223  return std::find_if(m_elements.begin(), m_elements.end(),
1224  [&key](const std::pair<utility::string_t, value>& p) {
1225  return p.first == key;
1226  });
1227  }
1228  else
1229  {
1230  auto iter = std::lower_bound(m_elements.begin(), m_elements.end(), key, compare_with_key);
1231  if (iter != m_elements.end() && key != iter->first)
1232  {
1233  return m_elements.end();
1234  }
1235  return iter;
1236  }
1237  }
1238 
1239  storage_type::iterator find_by_key(const utility::string_t& key)
1240  {
1241  auto iter = find_insert_location(key);
1242  if (iter != m_elements.end() && key != iter->first)
1243  {
1244  return m_elements.end();
1245  }
1246  return iter;
1247  }
1248 
1249  storage_type m_elements;
1250  bool m_keep_order;
1251  friend class details::_Object;
1252 
1253  template<typename CharType> friend class json::details::JSON_Parser;
1254  };
1255 
1259  class number
1260  {
1261  // Note that these constructors make sure that only negative integers are stored as signed int64 (while others convert to unsigned int64).
1262  // This helps handling number objects e.g. comparing two numbers.
1263 
1264  number(double value) : m_value(value), m_type(double_type) { }
1265  number(int32_t value) : m_intval(value), m_type(value < 0 ? signed_type : unsigned_type) { }
1266  number(uint32_t value) : m_intval(value), m_type(unsigned_type) { }
1267  number(int64_t value) : m_intval(value), m_type(value < 0 ? signed_type : unsigned_type) { }
1268  number(uint64_t value) : m_uintval(value), m_type(unsigned_type) { }
1269 
1270  public:
1271 
1276  _ASYNCRTIMP bool is_int32() const;
1277 
1282  _ASYNCRTIMP bool is_uint32() const;
1283 
1288  _ASYNCRTIMP bool is_int64() const;
1289 
1294  bool is_uint64() const
1295  {
1296  switch (m_type)
1297  {
1298  case signed_type : return m_intval >= 0;
1299  case unsigned_type : return true;
1300  case double_type :
1301  default :
1302  return false;
1303  }
1304  }
1305 
1310  double to_double() const
1311  {
1312  switch (m_type)
1313  {
1314  case double_type : return m_value;
1315  case signed_type : return static_cast<double>(m_intval);
1316  case unsigned_type : return static_cast<double>(m_uintval);
1317  default : return false;
1318  }
1319  }
1320 
1325  int32_t to_int32() const
1326  {
1327  if (m_type == double_type)
1328  return static_cast<int32_t>(m_value);
1329  else
1330  return static_cast<int32_t>(m_intval);
1331  }
1332 
1337  uint32_t to_uint32() const
1338  {
1339  if (m_type == double_type)
1340  return static_cast<uint32_t>(m_value);
1341  else
1342  return static_cast<uint32_t>(m_intval);
1343  }
1344 
1349  int64_t to_int64() const
1350  {
1351  if (m_type == double_type)
1352  return static_cast<int64_t>(m_value);
1353  else
1354  return static_cast<int64_t>(m_intval);
1355  }
1356 
1361  uint64_t to_uint64() const
1362  {
1363  if (m_type == double_type)
1364  return static_cast<uint64_t>(m_value);
1365  else
1366  return static_cast<uint64_t>(m_intval);
1367  }
1368 
1373  bool is_integral() const
1374  {
1375  return m_type != double_type;
1376  }
1377 
1383  bool operator==(const number &other) const
1384  {
1385  if (m_type != other.m_type)
1386  return false;
1387 
1388  switch (m_type)
1389  {
1390  case json::number::type::signed_type :
1391  return m_intval == other.m_intval;
1392  case json::number::type::unsigned_type :
1393  return m_uintval == other.m_uintval;
1394  case json::number::type::double_type :
1395  return m_value == other.m_value;
1396  }
1397  __assume(0);
1398  }
1399 
1400  private:
1401  union
1402  {
1403  int64_t m_intval;
1404  uint64_t m_uintval;
1405  double m_value;
1406  };
1407 
1408  enum type
1409  {
1410  signed_type=0, unsigned_type, double_type
1411  } m_type;
1412 
1413  friend class details::_Number;
1414  };
1415 
1416  namespace details
1417  {
1418  class _Value
1419  {
1420  public:
1421  virtual std::unique_ptr<_Value> _copy_value() = 0;
1422 
1423  virtual bool has_field(const utility::string_t &) const { return false; }
1424  virtual value get_field(const utility::string_t &) const { throw json_exception(_XPLATSTR("not an object")); }
1425  virtual value get_element(array::size_type) const { throw json_exception(_XPLATSTR("not an array")); }
1426 
1427  virtual value &index(const utility::string_t &) { throw json_exception(_XPLATSTR("not an object")); }
1428  virtual value &index(array::size_type) { throw json_exception(_XPLATSTR("not an array")); }
1429 
1430  virtual const value &cnst_index(const utility::string_t &) const { throw json_exception(_XPLATSTR("not an object")); }
1431  virtual const value &cnst_index(array::size_type) const { throw json_exception(_XPLATSTR("not an array")); }
1432 
1433  // Common function used for serialization to strings and streams.
1434  virtual void serialize_impl(std::string& str) const
1435  {
1436  format(str);
1437  }
1438 #ifdef _WIN32
1439  virtual void serialize_impl(std::wstring& str) const
1440  {
1441  format(str);
1442  }
1443 #endif
1444 
1445  virtual utility::string_t to_string() const
1446  {
1447  utility::string_t str;
1448  serialize_impl(str);
1449  return str;
1450  }
1451 
1452  virtual json::value::value_type type() const { return json::value::Null; }
1453 
1454  virtual bool is_integer() const { throw json_exception(_XPLATSTR("not a number")); }
1455  virtual bool is_double() const { throw json_exception(_XPLATSTR("not a number")); }
1456 
1457  virtual const json::number& as_number() { throw json_exception(_XPLATSTR("not a number")); }
1458  virtual double as_double() const { throw json_exception(_XPLATSTR("not a number")); }
1459  virtual int as_integer() const { throw json_exception(_XPLATSTR("not a number")); }
1460  virtual bool as_bool() const { throw json_exception(_XPLATSTR("not a boolean")); }
1461  virtual json::array& as_array() { throw json_exception(_XPLATSTR("not an array")); }
1462  virtual const json::array& as_array() const { throw json_exception(_XPLATSTR("not an array")); }
1463  virtual json::object& as_object() { throw json_exception(_XPLATSTR("not an object")); }
1464  virtual const json::object& as_object() const { throw json_exception(_XPLATSTR("not an object")); }
1465  virtual const utility::string_t& as_string() const { throw json_exception(_XPLATSTR("not a string")); }
1466 
1467  virtual size_t size() const { return 0; }
1468 
1469  virtual ~_Value() {}
1470 
1471  protected:
1472  _Value() {}
1473 
1474  virtual void format(std::basic_string<char>& stream) const
1475  {
1476  stream.append("null");
1477  }
1478 #ifdef _WIN32
1479  virtual void format(std::basic_string<wchar_t>& stream) const
1480  {
1481  stream.append(L"null");
1482  }
1483 #endif
1484  private:
1485 
1486  friend class web::json::value;
1487  };
1488 
1489  class _Null : public _Value
1490  {
1491  public:
1492  virtual std::unique_ptr<_Value> _copy_value()
1493  {
1494  return utility::details::make_unique<_Null>();
1495  }
1496  virtual json::value::value_type type() const { return json::value::Null; }
1497  };
1498 
1499  class _Number : public _Value
1500  {
1501  public:
1502  _Number(double value) : m_number(value) { }
1503  _Number(int32_t value) : m_number(value) { }
1504  _Number(uint32_t value) : m_number(value) { }
1505  _Number(int64_t value) : m_number(value) { }
1506  _Number(uint64_t value) : m_number(value) { }
1507 
1508  virtual std::unique_ptr<_Value> _copy_value()
1509  {
1510  return utility::details::make_unique<_Number>(*this);
1511  }
1512 
1513  virtual json::value::value_type type() const { return json::value::Number; }
1514 
1515  virtual bool is_integer() const { return m_number.is_integral(); }
1516  virtual bool is_double() const { return !m_number.is_integral(); }
1517 
1518  virtual double as_double() const
1519  {
1520  return m_number.to_double();
1521  }
1522 
1523  virtual int as_integer() const
1524  {
1525  return m_number.to_int32();
1526  }
1527 
1528  virtual const number& as_number() { return m_number; }
1529 
1530  protected:
1531  virtual void format(std::basic_string<char>& stream) const ;
1532 #ifdef _WIN32
1533  virtual void format(std::basic_string<wchar_t>& stream) const;
1534 #endif
1535  private:
1536  template<typename CharType> friend class json::details::JSON_Parser;
1537 
1538  json::number m_number;
1539  };
1540 
1541  class _Boolean : public _Value
1542  {
1543  public:
1544  _Boolean(bool value) : m_value(value) { }
1545 
1546  virtual std::unique_ptr<_Value> _copy_value()
1547  {
1548  return utility::details::make_unique<_Boolean>(*this);
1549  }
1550 
1551  virtual json::value::value_type type() const { return json::value::Boolean; }
1552 
1553  virtual bool as_bool() const { return m_value; }
1554 
1555  protected:
1556  virtual void format(std::basic_string<char>& stream) const
1557  {
1558  stream.append(m_value ? "true" : "false");
1559  }
1560 
1561 #ifdef _WIN32
1562  virtual void format(std::basic_string<wchar_t>& stream) const
1563  {
1564  stream.append(m_value ? L"true" : L"false");
1565  }
1566 #endif
1567  private:
1568  template<typename CharType> friend class json::details::JSON_Parser;
1569  bool m_value;
1570  };
1571 
1572  class _String : public _Value
1573  {
1574  public:
1575 
1576  _String(utility::string_t value) : m_string(std::move(value))
1577  {
1578  m_has_escape_char = has_escape_chars(*this);
1579  }
1580  _String(utility::string_t value, bool escaped_chars)
1581  : m_string(std::move(value)),
1582  m_has_escape_char(escaped_chars)
1583  { }
1584 
1585 #ifdef _WIN32
1586  _String(std::string &&value) : m_string(utility::conversions::to_utf16string(std::move(value)))
1587  {
1588  m_has_escape_char = has_escape_chars(*this);
1589  }
1590  _String(std::string &&value, bool escape_chars)
1591  : m_string(utility::conversions::to_utf16string(std::move(value))),
1592  m_has_escape_char(escape_chars)
1593  { }
1594 #endif
1595 
1596  virtual std::unique_ptr<_Value> _copy_value()
1597  {
1598  return utility::details::make_unique<_String>(*this);
1599  }
1600 
1601  virtual json::value::value_type type() const { return json::value::String; }
1602 
1603  virtual const utility::string_t & as_string() const;
1604 
1605  virtual void serialize_impl(std::string& str) const
1606  {
1607  serialize_impl_char_type(str);
1608  }
1609 #ifdef _WIN32
1610  virtual void serialize_impl(std::wstring& str) const
1611  {
1612  serialize_impl_char_type(str);
1613  }
1614 #endif
1615 
1616  protected:
1617  virtual void format(std::basic_string<char>& str) const;
1618 #ifdef _WIN32
1619  virtual void format(std::basic_string<wchar_t>& str) const;
1620 #endif
1621 
1622  private:
1623  friend class _Object;
1624  friend class _Array;
1625 
1626  size_t get_reserve_size() const
1627  {
1628  return m_string.size() + 2;
1629  }
1630 
1631  template <typename CharType>
1632  void serialize_impl_char_type(std::basic_string<CharType>& str) const
1633  {
1634  // To avoid repeated allocations reserve some space all up front.
1635  // size of string + 2 for quotes
1636  str.reserve(get_reserve_size());
1637  format(str);
1638  }
1639 
1640  std::string as_utf8_string() const;
1641  utf16string as_utf16_string() const;
1642 
1643  utility::string_t m_string;
1644 
1645  // There are significant performance gains that can be made by knowning whether
1646  // or not a character that requires escaping is present.
1647  bool m_has_escape_char;
1648  static bool has_escape_chars(const _String &str);
1649  };
1650 
1651  template<typename CharType>
1652  _ASYNCRTIMP void append_escape_string(std::basic_string<CharType>& str, const std::basic_string<CharType>& escaped);
1653 
1654  void format_string(const utility::string_t& key, utility::string_t& str);
1655 
1656 #ifdef _WIN32
1657  void format_string(const utility::string_t& key, std::string& str);
1658 #endif
1659 
1660  class _Object : public _Value
1661  {
1662  public:
1663 
1664  _Object(bool keep_order) : m_object(keep_order) { }
1665  _Object(object::storage_type fields, bool keep_order) : m_object(std::move(fields), keep_order) { }
1666 
1667  virtual std::unique_ptr<_Value> _copy_value()
1668  {
1669  return utility::details::make_unique<_Object>(*this);
1670  }
1671 
1672  virtual json::object& as_object() { return m_object; }
1673 
1674  virtual const json::object& as_object() const { return m_object; }
1675 
1676  virtual json::value::value_type type() const { return json::value::Object; }
1677 
1678  virtual bool has_field(const utility::string_t &) const;
1679 
1680  virtual json::value &index(const utility::string_t &key);
1681 
1682  bool is_equal(const _Object* other) const
1683  {
1684  if (m_object.size() != other->m_object.size())
1685  return false;
1686 
1687  return std::equal(std::begin(m_object), std::end(m_object), std::begin(other->m_object));
1688  }
1689 
1690  virtual void serialize_impl(std::string& str) const
1691  {
1692  // To avoid repeated allocations reserve some space all up front.
1693  str.reserve(get_reserve_size());
1694  format(str);
1695  }
1696 #ifdef _WIN32
1697  virtual void serialize_impl(std::wstring& str) const
1698  {
1699  // To avoid repeated allocations reserve some space all up front.
1700  str.reserve(get_reserve_size());
1701  format(str);
1702  }
1703 #endif
1704  size_t size() const { return m_object.size(); }
1705 
1706  protected:
1707  virtual void format(std::basic_string<char>& str) const
1708  {
1709  format_impl(str);
1710  }
1711 #ifdef _WIN32
1712  virtual void format(std::basic_string<wchar_t>& str) const
1713  {
1714  format_impl(str);
1715  }
1716 #endif
1717 
1718  private:
1719  json::object m_object;
1720 
1721  template<typename CharType> friend class json::details::JSON_Parser;
1722 
1723  template<typename CharType>
1724  void format_impl(std::basic_string<CharType>& str) const
1725  {
1726  str.push_back('{');
1727  if(!m_object.empty())
1728  {
1729  auto lastElement = m_object.end() - 1;
1730  for (auto iter = m_object.begin(); iter != lastElement; ++iter)
1731  {
1732  format_string(iter->first, str);
1733  str.push_back(':');
1734  iter->second.format(str);
1735  str.push_back(',');
1736  }
1737  format_string(lastElement->first, str);
1738  str.push_back(':');
1739  lastElement->second.format(str);
1740  }
1741  str.push_back('}');
1742  }
1743 
1744  size_t get_reserve_size() const
1745  {
1746  // This is a heuristic we can tune more in the future:
1747  // Basically size of string plus
1748  // sum size of value if an object, array, or string.
1749  size_t reserveSize = 2; // For brackets {}
1750  for(auto iter = m_object.begin(); iter != m_object.end(); ++iter)
1751  {
1752  reserveSize += iter->first.length() + 2; // 2 for quotes
1753  size_t valueSize = iter->second.size() * 20; // Multipler by each object/array element
1754  if(valueSize == 0)
1755  {
1756  if(iter->second.type() == json::value::String)
1757  {
1758  valueSize = static_cast<_String *>(iter->second.m_value.get())->get_reserve_size();
1759  }
1760  else
1761  {
1762  valueSize = 5; // true, false, or null
1763  }
1764  }
1765  reserveSize += valueSize;
1766  }
1767  return reserveSize;
1768  }
1769  };
1770 
1771  class _Array : public _Value
1772  {
1773  public:
1774  _Array() {}
1775  _Array(array::size_type size) : m_array(size) {}
1776  _Array(array::storage_type elements) : m_array(std::move(elements)) { }
1777 
1778  virtual std::unique_ptr<_Value> _copy_value()
1779  {
1780  return utility::details::make_unique<_Array>(*this);
1781  }
1782 
1783  virtual json::value::value_type type() const { return json::value::Array; }
1784 
1785  virtual json::array& as_array() { return m_array; }
1786  virtual const json::array& as_array() const { return m_array; }
1787 
1788  virtual json::value &index(json::array::size_type index)
1789  {
1790  return m_array[index];
1791  }
1792 
1793  bool is_equal(const _Array* other) const
1794  {
1795  if ( m_array.size() != other->m_array.size())
1796  return false;
1797 
1798  auto iterT = m_array.cbegin();
1799  auto iterO = other->m_array.cbegin();
1800  auto iterTe = m_array.cend();
1801  auto iterOe = other->m_array.cend();
1802 
1803  for (; iterT != iterTe && iterO != iterOe; ++iterT, ++iterO)
1804  {
1805  if ( *iterT != *iterO )
1806  return false;
1807  }
1808 
1809  return true;
1810  }
1811 
1812  virtual void serialize_impl(std::string& str) const
1813  {
1814  // To avoid repeated allocations reserve some space all up front.
1815  str.reserve(get_reserve_size());
1816  format(str);
1817  }
1818 #ifdef _WIN32
1819  virtual void serialize_impl(std::wstring& str) const
1820  {
1821  // To avoid repeated allocations reserve some space all up front.
1822  str.reserve(get_reserve_size());
1823  format(str);
1824  }
1825 #endif
1826  size_t size() const { return m_array.size(); }
1827 
1828  protected:
1829  virtual void format(std::basic_string<char>& str) const
1830  {
1831  format_impl(str);
1832  }
1833 #ifdef _WIN32
1834  virtual void format(std::basic_string<wchar_t>& str) const
1835  {
1836  format_impl(str);
1837  }
1838 #endif
1839  private:
1840  json::array m_array;
1841 
1842  template<typename CharType> friend class json::details::JSON_Parser;
1843 
1844  template<typename CharType>
1845  void format_impl(std::basic_string<CharType>& str) const
1846  {
1847  str.push_back('[');
1848  if(!m_array.m_elements.empty())
1849  {
1850  auto lastElement = m_array.m_elements.end() - 1;
1851  for (auto iter = m_array.m_elements.begin(); iter != lastElement; ++iter)
1852  {
1853  iter->format(str);
1854  str.push_back(',');
1855  }
1856  lastElement->format(str);
1857  }
1858  str.push_back(']');
1859  }
1860 
1861  size_t get_reserve_size() const
1862  {
1863  // This is a heuristic we can tune more in the future:
1864  // Basically sum size of each value if an object, array, or string by a multiplier.
1865  size_t reserveSize = 2; // For brackets []
1866  for(auto iter = m_array.cbegin(); iter != m_array.cend(); ++iter)
1867  {
1868  size_t valueSize = iter->size() * 20; // Per each nested array/object
1869 
1870  if(valueSize == 0)
1871  valueSize = 5; // true, false, or null
1872 
1873  reserveSize += valueSize;
1874  }
1875  return reserveSize;
1876  }
1877  };
1878  } // namespace details
1879 
1884  inline size_t json::value::size() const
1885  {
1886  return m_value->size();
1887  }
1888 
1894  inline bool json::value::has_field(const utility::string_t& key) const
1895  {
1896  return m_value->has_field(key);
1897  }
1898 
1904  inline json::value json::value::get(const utility::string_t& key) const
1905  {
1906  return m_value->get_field(key);
1907  }
1908 
1914  inline json::value json::value::get(size_t index) const
1915  {
1916  return m_value->get_element(index);
1917  }
1918 
1925  _ASYNCRTIMP utility::ostream_t& __cdecl operator << (utility::ostream_t &os, const json::value &val);
1926 
1933  _ASYNCRTIMP utility::istream_t& __cdecl operator >> (utility::istream_t &is, json::value &val);
1934 }}
1935 
1936 #endif
bool operator==(const number &other) const
Compares two JSON numbers for equality.
Definition: json.h:1383
bool is_integral() const
Is the number represented internally as an integral type?
Definition: json.h:1373
A JSON array represented as a C++ class.
Definition: json.h:752
Boolean value.
Definition: json.h:94
_ASYNCRTIMP bool is_uint32() const
Does the number fit into unsigned int32?
Number value.
Definition: json.h:92
int32_t to_int32() const
Converts the JSON number to int32.
Definition: json.h:1325
const_reverse_iterator crbegin() const
Gets the beginning const reverse iterator element of the object.
Definition: json.h:1077
json::value & operator[](size_type index)
Accesses an element of a JSON array.
Definition: json.h:932
static _ASYNCRTIMP json::value __cdecl object(bool keep_order=false)
Creates an object value
value get(const utility::string_t &key) const
Accesses a field of a JSON object.
const json::value & at(size_type index) const
Accesses an element of a JSON array. Throws when index out of bounds.
Definition: json.h:919
reverse_iterator rbegin()
Gets the beginning reverse iterator element of the object
Definition: json.h:1023
Object value.
Definition: json.h:98
void erase(const utility::string_t &key)
Deletes an element of the JSON object. If the key doesn't exist, this method throws.
Definition: json.h:1106
const_iterator end() const
Gets the end const iterator element of the object.
Definition: json.h:1014
Definition: json.h:1572
size_type size() const
Gets the number of elements of the array.
Definition: json.h:947
_ASYNCRTIMP int as_integer() const
Converts the JSON value to a C++ integer, if and only if it is a number value. Throws json_exception ...
const_iterator cend() const
Gets the end const iterator element of the array.
Definition: json.h:854
_ASYNCRTIMP bool is_int64() const
Does the number fit into int64?
bool has_field(const utility::string_t &key) const
Tests for the presence of a field.
Definition: json.h:1894
iterator begin()
Gets the beginning iterator element of the object
Definition: json.h:987
Null value.
Definition: json.h:102
const_reverse_iterator crend() const
Gets the end const reverse iterator element of the object.
Definition: json.h:1086
bool is_string() const
Is the current value a string value?
Definition: json.h:386
bool is_number() const
Is the current value a number value?
Definition: json.h:354
_ASYNCRTIMP json::array & as_array()
Converts the JSON value to a json array, if and only if it is an array value.
Definition: json.h:1418
reverse_iterator rend()
Gets the end reverse iterator element of the array
Definition: json.h:827
A JSON number represented as a C++ class.
Definition: json.h:1259
uint64_t to_uint64() const
Converts the JSON number to unsigned int64.
Definition: json.h:1361
The web namespace contains functionality common to multiple protocols like HTTP and WebSockets...
Definition: base_uri.h:37
_ASYNCRTIMP json::object & as_object()
Converts the JSON value to a json object, if and only if it is an object value.
const_iterator find(const utility::string_t &key) const
Gets an iterator to an element of a JSON object.
Definition: json.h:1171
bool is_null() const
Is the current value a null value?
Definition: json.h:348
value_type
This enumeration represents the various kinds of JSON values.
Definition: json.h:89
_ASYNCRTIMP bool as_bool() const
Converts the JSON value to a C++ bool, if and only if it is a Boolean value.
bool is_array() const
Is the current value an array?
Definition: json.h:392
iterator erase(iterator position)
Deletes an element of the JSON array.
Definition: json.h:883
size_t size() const
Gets the number of children of the value.
Definition: json.h:1884
iterator begin()
Gets the beginning iterator element of the array
Definition: json.h:773
_ASYNCRTIMP utility::ostream_t &__cdecl operator<<(utility::ostream_t &os, const json::value &val)
A standard std::ostream operator to facilitate writing JSON values to streams.
iterator end()
Gets the end iterator element of the array
Definition: json.h:791
bool is_uint64() const
Does the number fit into unsigned int64?
Definition: json.h:1294
Definition: json.h:54
_ASYNCRTIMP utility::string_t serialize() const
Serializes the current JSON value to a C++ string.
_ASYNCRTIMP utility::string_t __cdecl to_string_t(std::string &&s)
Converts to a platform dependent Unicode string type.
const_iterator cbegin() const
Gets the beginning const iterator element of the object.
Definition: json.h:1059
const_reverse_iterator crend() const
Gets the end const reverse iterator element of the array.
Definition: json.h:872
const_reverse_iterator rend() const
Gets the end const reverse iterator element of the object
Definition: json.h:1050
reverse_iterator rend()
Gets the end reverse iterator element of the object
Definition: json.h:1041
bool operator!=(const value &other) const
Compares two JSON values for inequality.
Definition: json.h:547
bool empty() const
Checks if there are any elements in the JSON object.
Definition: json.h:1189
_ASYNCRTIMP bool is_int32() const
Does the number fit into int32?
Definition: json.h:1499
_ASYNCRTIMP utf16string __cdecl to_utf16string(const std::string &value)
Converts to a UTF-16 from string.
json::value & operator[](const utility::string_t &key)
Accesses an element of a JSON object.
Definition: json.h:1154
const json::value & at(const utility::string_t &key) const
Accesses an element of a JSON object. If the key doesn't exist, this method throws.
Definition: json.h:1138
_ASYNCRTIMP json::value & at(size_t index)
Accesses an element of a JSON array. Throws when index out of bounds.
Definition: json.h:1541
void _ASYNCRTIMP __cdecl keep_object_element_order(bool keep_order)
Preserve the order of the name/value pairs when parsing a JSON object. The default is false...
static _ASYNCRTIMP value __cdecl parse(const utility::string_t &value)
Parses a string and construct a JSON value.
const_reverse_iterator rbegin() const
Gets the beginning const reverse iterator element of the array
Definition: json.h:818
reverse_iterator rbegin()
Gets the beginning reverse iterator element of the array
Definition: json.h:809
bool is_boolean() const
Is the current value a Boolean value?
Definition: json.h:380
A JSON object represented as a C++ class.
Definition: json.h:962
iterator erase(iterator position)
Deletes an element of the JSON object.
Definition: json.h:1097
const_iterator begin() const
Gets the beginning const iterator element of the array.
Definition: json.h:782
_ASYNCRTIMP bool is_integer() const
Is the current value represented as an integer number value?
A JSON value represented as a C++ class.
Definition: json.h:83
static _ASYNCRTIMP value __cdecl null()
Creates a null value
A single exception type to represent errors in parsing, converting, and accessing elements of JSON va...
Definition: json.h:675
Definition: json.h:1660
const_reverse_iterator rend() const
Gets the end const reverse iterator element of the array
Definition: json.h:836
const_iterator end() const
Gets the end const iterator element of the array.
Definition: json.h:800
static _ASYNCRTIMP value __cdecl string(utility::string_t value)
Creates a string value
bool is_object() const
Is the current value an object?
Definition: json.h:398
static _ASYNCRTIMP json::value __cdecl array()
Creates an empty JSON array
_ASYNCRTIMP double as_double() const
Converts the JSON value to a C++ double, if and only if it is a number value. Throws json_exception i...
const_reverse_iterator crbegin() const
Gets the beginning const reverse iterator element of the array.
Definition: json.h:863
iterator end()
Gets the end iterator element of the object
Definition: json.h:1005
const_iterator cend() const
Gets the end const iterator element of the object.
Definition: json.h:1068
json::value & at(size_type index)
Accesses an element of a JSON array. Throws when index out of bounds.
Definition: json.h:906
_ASYNCRTIMP utility::istream_t &__cdecl operator>>(utility::istream_t &is, json::value &val)
A standard std::istream operator to facilitate reading JSON values from streams.
double to_double() const
Converts the JSON number to a C++ double.
Definition: json.h:1310
_ASYNCRTIMP bool is_double() const
Is the current value represented as an double number value?
String value.
Definition: json.h:96
_ASYNCRTIMP json::value::value_type type() const
Accesses the type of JSON value the current value instance is
Definition: json.h:1771
_ASYNCRTIMP const json::number & as_number() const
Converts the JSON value to a number class, if and only if it is a number value. Throws json_exception...
Definition: json.h:1489
_ASYNCRTIMP bool operator==(const value &other) const
Compares two JSON values for equality.
_ASYNCRTIMP value & operator[](const utility::string_t &key)
Accesses a field of a JSON object.
size_type size() const
Gets the number of elements of the object.
Definition: json.h:1180
_ASYNCRTIMP value()
Constructor creating a null value
Array value.
Definition: json.h:100
Definition: SafeInt3.hpp:5564
uint32_t to_uint32() const
Converts the JSON number to unsigned int32.
Definition: json.h:1337
_ASYNCRTIMP std::string __cdecl to_utf8string(std::string value)
Converts to a UTF-8 string.
Various utilities for string conversions and date and time manipulation.
Definition: asyncrt_utils.h:50
int64_t to_int64() const
Converts the JSON number to int64.
Definition: json.h:1349
_ASYNCRTIMP void erase(size_t index)
Erases an element of a JSON array. Throws if index is out of bounds.
const_iterator cbegin() const
Gets the beginning const iterator element of the array.
Definition: json.h:845
json::value & at(const utility::string_t &key)
Accesses an element of a JSON object. If the key doesn't exist, this method throws.
Definition: json.h:1122
_ASYNCRTIMP const utility::string_t & as_string() const
Converts the JSON value to a C++ STL string, if and only if it is a string value. ...
const_reverse_iterator rbegin() const
Gets the beginning const reverse iterator element of the object
Definition: json.h:1032
const_iterator begin() const
Gets the beginning const iterator element of the object.
Definition: json.h:996
void erase(size_type index)
Deletes the element at an index of the JSON array.
Definition: json.h:892