Devel Lib
JsonSerializableType.h
1 #pragma once
2 
3 #include "Core/Global.h"
4 #include "Core/Exceptions.h"
5 #include "Serializing/Json/JsonFieldName.h"
6 #include "Serializing/SerializingDefines.h"
7 #include "Serializing/Core/SerializableData.h"
8 #include "IO/JsonObject/JsonObject.h"
9 
12 namespace Devel::Serializing {
14  static auto InvalidObjectName = std::runtime_error("Object invalid or empty name!");
16  static auto InvalidData = std::runtime_error("Object does not matches the struct!");
18  static auto DifferentTypesException = std::runtime_error("Different types!");
20  static auto InvalidTypeException = std::runtime_error("Invalid type!");
21 
22 #pragma pack(push, 1)
23 
83  template<typename T = int, typename TData = IData<T>>
84  class IJsonType : public TData {
85  protected:
88  explicit IJsonType(const CJsonFieldName i_oFieldName) : m_oFieldName(i_oFieldName), m_bIsNull(false) {}
89 
91  virtual ~IJsonType() = default;
92 
93  private:
96  CJsonFieldName m_oFieldName;
99  IBool<true> m_bIsNull;
100  protected:
105  virtual bool onDeserialize(IO::CJsonObject &i_oObject, const bool i_bIsStrict) {
106  return true;
107  };
108 
113  virtual bool onSerialize(IO::CJsonObject &i_oObject, const bool i_bIsStrict) const {
114  return true;
115  }
116 
120  virtual bool onDeserialize(IO::CJsonObject &i_oObject) {
121  return this->onDeserialize(i_oObject, false);
122  }
123 
127  virtual bool onSerialize(IO::CJsonObject &i_oObject) const {
128  return this->onSerialize(i_oObject, false);
129  }
130 
131  protected:
142  bool serialize(IO::CJsonObject &i_oObject, const bool i_bIsStrict = false) const {
143  if (checkSerializeObject(i_oObject, i_bIsStrict)) {
144  return true;
145  }
146 
147  if (std::is_arithmetic_v<T>) {
148  i_oObject.get(this->name()) = static_cast<T>(this->m_tValue);
149  } else {
150  i_oObject.get(this->name()) = this->m_tValue;
151  }
152  return true;
153  }
154 
157  [[nodiscard]] std::string_view name() const {
158  return this->m_oFieldName.name();
159  }
160 
163  [[nodiscard]] bool isNull() const {
164  return this->m_bIsNull;
165  }
166 
169  void setNull(bool i_bState) {
170  this->m_bIsNull = i_bState;
171  }
172 
177  IO::CJsonObject *getObject(IO::CJsonObject &i_oObject, const bool i_bIsStrict) {
178  IO::CJsonObject *pObject = (i_oObject.type() != IO::EJsonType::JTArray)
179  ? i_oObject.find(this->name())
180  : ((this->name().empty()) ? &i_oObject
181  : i_oObject.find(this->name())
182  );
183 
184  if (!pObject) {
185  if (i_bIsStrict) {
186  throw InvalidData;
187  }
188  IJsonType::setNull(true);
189  } else if (pObject->type() == IO::EJsonType::JTNull) {
190  IJsonType::setNull(true);
191  pObject = nullptr;
192  }
193  return pObject;
194  }
195 
200  bool checkSerializeObject(IO::CJsonObject &i_oObject, const bool i_bIsStrict) const {
201  if (!i_bIsStrict && this->isNull()) {
202  return true;
203  }
204 
205  if (this->name().empty()) {
206  throw InvalidObjectName;
207  }
208 
209  if (this->isNull()) {
210  i_oObject.get(this->name()).setNull();
211  }
212 
213  return false;
214  }
215 
216  public:
221  bool doDeserialize(IO::CJsonObject &i_oObject, const bool i_bIsStrict = false) {
222  return this->onDeserialize(i_oObject, i_bIsStrict);
223  }
224 
229  bool doSerialize(IO::CJsonObject &i_oObject, const bool i_bIsStrict = false) const {
230  return this->onSerialize(i_oObject, i_bIsStrict);
231  }
232 
233  public:
236  [[nodiscard]] size_t size() const override {
237  return sizeof(*this);
238  }
239 
240  public:
241  using TData::TData;
242 
247  template<typename TJsonFieldName,
248  std::enable_if_t<std::is_same_v<CJsonFieldName, TJsonFieldName>, bool> = true
249  >
250  IJsonType &operator=(const TJsonFieldName &i_tValue) {
251  this->m_oFieldName = i_tValue;
252  return *this;
253  }
254 
259  template<typename TJsonFieldName,
260  std::enable_if_t<std::is_same_v<CJsonFieldName, TJsonFieldName>, bool> = true
261  >
262  IJsonType &operator=(TJsonFieldName &&i_tValue) {
263  this->m_oFieldName = std::move(i_tValue);
264  return *this;
265  };
266  };
267 
268 #pragma pack(pop)
269 
276  template<typename TField, typename TStruct>
277  TField *GetJsonFieldByName(TStruct &i_oStruct, const std::string_view i_sName) {
278  TField *pField = nullptr;
279  IterateSerializableStruct<TField>(&i_oStruct, [&](TField *i_pData) {
280  if (i_pData->name() == i_sName) {
281  pField = i_pData;
282  return false;
283  }
284 
285  return true;
286  });
287 
288  return pField;
289  }
290 
291  std::false_type is_json_type_class_impl(...);
292 
293  template<typename T = int, typename TData = IData<T>>
294  std::true_type is_json_type_class_impl(IJsonType<T, TData> *);
295 
298  template<typename T>
299  using is_json_type_class = decltype(is_json_type_class_impl(std::declval<T *>()));
300 }
A class that encapsulates a JSON object.
Definition: JsonObject.h:50
void setNull()
Sets the type of the JSON object to null.
Definition: JsonObject.h:132
EJsonType type() const
Returns the type of the JSON object.
Definition: JsonObject.h:123
CJsonObject * find(std::string_view i_stName)
Finds a value in the JSON object.
Definition: JsonObject.cpp:17
CJsonObject & get(const std::string_view i_stName)
Gets the value associated with the specified name.
Definition: JsonObject.h:128
A class representing a JSON field name.
Definition: JsonFieldName.h:49
const char * name() const
Retrieves the underlying name string.
Definition: JsonFieldName.h:88
Represents a JSON data type with serialization and deserialization functionality.
Definition: JsonSerializableType.h:84
bool isNull() const
Checks if the JSON field is null.
Definition: JsonSerializableType.h:163
virtual ~IJsonType()=default
Destructor.
IO::CJsonObject * getObject(IO::CJsonObject &i_oObject, const bool i_bIsStrict)
Retrieves the JSON object for the specified JSON field.
Definition: JsonSerializableType.h:177
virtual bool onDeserialize(IO::CJsonObject &i_oObject, const bool i_bIsStrict)
Called during deserialization to populate the object from a JSON object.
Definition: JsonSerializableType.h:105
virtual bool onSerialize(IO::CJsonObject &i_oObject) const
Called during deserialization to populate the object from a JSON object (non-strict mode).
Definition: JsonSerializableType.h:127
std::string_view name() const
Retrieves the name of the JSON field.
Definition: JsonSerializableType.h:157
bool serialize(IO::CJsonObject &i_oObject, const bool i_bIsStrict=false) const
Serializes the data to a JSON object.
Definition: JsonSerializableType.h:142
bool doSerialize(IO::CJsonObject &i_oObject, const bool i_bIsStrict=false) const
Serializes the object to a JSON object.
Definition: JsonSerializableType.h:229
virtual bool onDeserialize(IO::CJsonObject &i_oObject)
Called during deserialization to populate the object from a JSON object (non-strict mode).
Definition: JsonSerializableType.h:120
void setNull(bool i_bState)
Sets the null state of the JSON field.
Definition: JsonSerializableType.h:169
IJsonType & operator=(const TJsonFieldName &i_tValue)
Assigns a JSON field name to the object.
Definition: JsonSerializableType.h:250
IJsonType & operator=(TJsonFieldName &&i_tValue)
Assigns a JSON field name to the object (move assignment).
Definition: JsonSerializableType.h:262
bool checkSerializeObject(IO::CJsonObject &i_oObject, const bool i_bIsStrict) const
Checks if serialization of the object is allowed and handles null fields.
Definition: JsonSerializableType.h:200
bool doDeserialize(IO::CJsonObject &i_oObject, const bool i_bIsStrict=false)
Deserializes the object from a JSON object.
Definition: JsonSerializableType.h:221
virtual bool onSerialize(IO::CJsonObject &i_oObject, const bool i_bIsStrict) const
Called during serialization to convert the object to a JSON object.
Definition: JsonSerializableType.h:113
size_t size() const override
Retrieves the size of the object.
Definition: JsonSerializableType.h:236
IJsonType(const CJsonFieldName i_oFieldName)
Constructs an IJsonType object with the specified JSON field name.
Definition: JsonSerializableType.h:88
int m_tValue
The value.
Definition: SerializableData.h:78
@ JTNull
A null type.
@ JTArray
An array type (an ordered collection of values).
The namespace encapsulating serializing related functionality in the Devel framework.
decltype(is_json_type_class_impl(std::declval< T * >())) is_json_type_class
Checks if a type is a JSON type class.
Definition: JsonSerializableType.h:299
TField * GetJsonFieldByName(TStruct &i_oStruct, const std::string_view i_sName)
Retrieves a JSON field by name from a struct.
Definition: JsonSerializableType.h:277