tgbotxx  1.1.6.9
Telegram Bot C++ Library
Object.hpp
Go to the documentation of this file.
1 #pragma once
3 #include <type_traits>
4 #include <cstdint>
5 #include <ctime>
6 #include <iostream>
7 #include <memory>
8 #include <nlohmann/json.hpp>
9 #include <sstream>
10 #include <string>
11 #include <tgbotxx/Exception.hpp>
12 #include <tgbotxx/utils/Ptr.hpp>
13 #include <vector>
14 namespace nl = nlohmann;
15 
17 
19 #define OBJECT_SERIALIZE_FIELD(json, json_field, field) \
20  json[json_field] = field;
21 
22 #define OBJECT_SERIALIZE_FIELD_PTR(json, json_field, field) \
23  if (field) { \
24  json[json_field] = field->toJson(); \
25  }
26 
27 #define OBJECT_SERIALIZE_FIELD_PTR_ARRAY(json, json_field, array_field) \
28  json[json_field] = nl::json::array(); \
29  for (const auto& e: array_field) \
30  json[json_field].push_back(e->toJson());
31 
32 #define OBJECT_SERIALIZE_FIELD_PTR_ARRAY_ARRAY(json, json_field, array_array_field) \
33  json[json_field] = nl::json::array(); \
34  for (const auto& array: array_array_field) { \
35  nl::json arr = nl::json::array(); \
36  for (const auto& e: array) { \
37  arr.push_back(e->toJson()); \
38  } \
39  json[json_field].push_back(arr); \
40  }
41 
42 
44 #define OBJECT_DESERIALIZE_FIELD(json, json_field, field, default_value, optional) \
45  if (json.contains(json_field)) { \
46  try { \
47  using T = std::remove_reference_t<std::remove_const_t<decltype(field)>>; \
48  field = json[json_field].get<T>(); \
49  } catch (const std::exception& e) { \
50  std::ostringstream err{}; \
51  err << __FILE__ << ':' << __LINE__ << ": " << __FUNCTION__ << ": Failed to deserialize \"" \
52  << json_field << "\" from json object: " << json.dump(2) << "\nReason: " << e.what(); \
53  throw Exception(err.str()); \
54  } catch (...) { \
55  std::ostringstream err{}; \
56  err << __FILE__ << ':' << __LINE__ << ": " << __FUNCTION__ << ": Failed to deserialize \"" \
57  << json_field << "\" from json object: " << json.dump(2); \
58  throw Exception(err.str()); \
59  } \
60  } else { \
61  if (not(optional)) { \
62  std::ostringstream err{}; \
63  err << __FILE__ << ':' << __LINE__ << ": " << __FUNCTION__ << ": Missing required field \"" \
64  << json_field << "\" from json object: " << json.dump(2); \
65  throw Exception(err.str()); \
66  } \
67  field = default_value; \
68  }
69 
70 #define OBJECT_DESERIALIZE_FIELD_PTR(json, json_field, field, optional) \
71  static_assert(!std::is_const_v<decltype(field)>, "OBJECT_DESERIALIZE_FIELD_PTR: 'field' must not be const"); \
72  static_assert(std::is_same_v<decltype(optional), bool>, "OBJECT_DESERIALIZE_FIELD_PTR: 'optional' must be boolean"); \
73  if (json.contains(json_field) and json[json_field].is_object() and not json[json_field].empty()) { \
74  using T = std::remove_reference_t<decltype(field)>; \
75  using E = T::element_type; \
76  field.reset(new (E)(json[json_field])); \
77  } else { \
78  if (not(optional)) { \
79  std::ostringstream err{}; \
80  err << __FILE__ << ':' << __LINE__ << ": " << __FUNCTION__ << ": Missing required field \"" \
81  << json_field << "\" from json object: " << json.dump(2); \
82  throw Exception(err.str()); \
83  } \
84  field = nullptr; \
85  }
86 
87 #define OBJECT_DESERIALIZE_FIELD_PTR_ARRAY(json, json_field, array_field, optional) \
88  static_assert(!std::is_const_v<decltype(array_field)>, "OBJECT_DESERIALIZE_FIELD_PTR_ARRAY: 'field' must not be const"); \
89  static_assert(std::is_same_v<decltype(optional), bool>, "OBJECT_DESERIALIZE_FIELD_PTR_ARRAY: 'optional' must be boolean"); \
90  if ((json.contains(json_field)) and (json[json_field].is_array())) { \
91  using T = std::remove_reference_t<std::remove_const_t<decltype(array_field)::value_type>>; \
92  using E = T::element_type; \
93  array_field.reserve(json[json_field].size()); \
94  for (const nl::json& obj: json[json_field]) { \
95  array_field.emplace_back(new E(obj)); \
96  } \
97  } else { \
98  if (not(optional)) { \
99  std::ostringstream err{}; \
100  err << __FILE__ << ':' << __LINE__ << ": " << __FUNCTION__ << ": Missing required field \"" \
101  << json_field << "\" from json object: " << json.dump(2); \
102  throw Exception(err.str()); \
103  } \
104  array_field.clear(); \
105  }
106 
107 
108 #define OBJECT_DESERIALIZE_FIELD_PTR_ARRAY_ARRAY(json, json_field, array_array_field, optional) \
109  static_assert(!std::is_const_v<decltype(array_array_field)>, "OBJECT_DESERIALIZE_FIELD_PTR_ARRAY_ARRAY: 'field' must not be const"); \
110  static_assert(std::is_same_v<decltype(optional), bool>, "OBJECT_DESERIALIZE_FIELD_PTR_ARRAY_ARRAY: 'optional' must be boolean"); \
111  if ((json.contains(json_field)) and (json[json_field].is_array())) { \
112  using ArrayArray = decltype(array_array_field); \
113  using Array = ArrayArray::value_type; /* e.g vector<vector<int> <- > */ \
114  using T = ArrayArray::value_type::value_type; /* e.g vector<vector<int>> <- */ \
115  using E = T::element_type; \
116  array_array_field.reserve(json[json_field].size()); \
117  for (const nl::json& array: json[json_field]) { \
118  Array arr; \
119  arr.reserve(array.size()); \
120  for (const nl::json& obj: array) { \
121  arr.emplace_back(new E(obj)); \
122  } \
123  array_array_field.push_back(std::move(arr)); \
124  } \
125  } else { \
126  if (not(optional)) { \
127  std::ostringstream err{}; \
128  err << __FILE__ << ':' << __LINE__ << ": " << __FUNCTION__ << ": Missing required field \"" \
129  << json_field << "\" from json object: " << json.dump(2); \
130  throw Exception(err.str()); \
131  } \
132  array_array_field.clear(); \
133  }