1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #ifndef OHOS_DISTRIBUTED_DATA_FRAMEWORKS_COMMON_SERIALIZABLE_H
17 #define OHOS_DISTRIBUTED_DATA_FRAMEWORKS_COMMON_SERIALIZABLE_H
18 #include <string>
19 #include <vector>
20 #include "visibility.h"
21 #ifndef JSON_NOEXCEPTION
22 #define JSON_NOEXCEPTION
23 #endif
24 #include <variant>
25 #include <nlohmann/json.hpp>
26 namespace OHOS {
27 namespace DistributedData {
28 #ifndef GET_NAME
29 #define GET_NAME(value) #value
30 #endif
31 struct Serializable {
32 public:
33 using json = nlohmann::json;
34 using size_type = nlohmann::json::size_type;
35 using error_handler_t = nlohmann::detail::error_handler_t;
36
37 API_EXPORT json Marshall() const;
38 template<typename T>
MarshallSerializable39 static std::string Marshall(T &values)
40 {
41 json root;
42 SetValue(root, values);
43 return root.dump(-1, ' ', false, error_handler_t::replace);
44 }
45
46 API_EXPORT bool Unmarshall(const std::string &jsonStr);
47 template<typename T>
UnmarshallSerializable48 static bool Unmarshall(const std::string &body, T &values)
49 {
50 return GetValue(ToJson(body), "", values);
51 }
52 API_EXPORT static json ToJson(const std::string &jsonStr);
53 API_EXPORT static bool IsJson(const std::string &jsonStr);
54 virtual bool Marshal(json &node) const = 0;
55 virtual bool Unmarshal(const json &node) = 0;
56 API_EXPORT static bool GetValue(const json &node, const std::string &name, std::string &value);
57 API_EXPORT static bool GetValue(const json &node, const std::string &name, uint32_t &value);
58 API_EXPORT static bool GetValue(const json &node, const std::string &name, int32_t &value);
59 API_EXPORT static bool GetValue(const json &node, const std::string &name, int64_t &value);
60 API_EXPORT static bool GetValue(const json &node, const std::string &name, uint64_t &value);
61 API_EXPORT static bool GetValue(const json &node, const std::string &name, bool &value);
62 API_EXPORT static bool GetValue(const json &node, const std::string &name, std::vector<uint8_t> &value);
63 API_EXPORT static bool GetValue(const json &node, const std::string &name, Serializable &value);
64 API_EXPORT static bool SetValue(json &node, const std::string &value);
65 API_EXPORT static bool SetValue(json &node, const uint32_t &value);
66 API_EXPORT static bool SetValue(json &node, const int32_t &value);
67 API_EXPORT static bool SetValue(json &node, const int64_t &value);
68 API_EXPORT static bool SetValue(json &node, const double &value);
69 API_EXPORT static bool SetValue(json &node, const uint64_t &value);
70 // Use bool & to forbid the const T * auto convert to bool, const bool will convert to const uint32_t &value;
71 template<typename T>
SetValueSerializable72 API_EXPORT static std::enable_if_t<std::is_same_v<T, bool>, bool> SetValue(json &node, const T &value)
73 {
74 node = static_cast<bool>(value);
75 return true;
76 }
77
78 API_EXPORT static bool SetValue(json &node, const std::vector<uint8_t> &value);
79 API_EXPORT static bool SetValue(json &node, const Serializable &value);
80
81 template<typename... _Types>
82 API_EXPORT static bool SetValue(json &node, const std::variant<_Types...> &input);
83
84 template<typename... _Types>
85 API_EXPORT static bool GetValue(const json &node, const std::string &name, std::variant<_Types...> &value);
86 protected:
87 API_EXPORT ~Serializable() = default;
88
89 template<typename T>
90 static bool GetValue(const json &node, const std::string &name, std::vector<T> &values);
91
92 template<typename T>
93 static bool SetValue(json &node, const std::vector<T> &values);
94
95 template<typename T>
96 static bool GetValue(const json &node, const std::string &name, std::map<std::string, T> &values);
97
98 template<typename T>
99 static bool SetValue(json &node, const std::map<std::string, T> &values);
100
101 template<typename T>
102 static bool GetValue(const json &node, const std::string &name, T *&value);
103
104 template<typename T>
105 static bool SetValue(json &node, const T *value);
106
107 template<typename _OutTp>
108 static bool ReadVariant(const json &node, const std::string &name, uint32_t step, uint32_t index, _OutTp &output);
109
110 template<typename _OutTp, typename _First, typename... _Rest>
111 static bool ReadVariant(const json &node, const std::string &name, uint32_t step, uint32_t index, _OutTp &output);
112
113 template<typename _InTp>
114 static bool WriteVariant(json &node, uint32_t step, const _InTp &input);
115
116 template<typename _InTp, typename _First, typename... _Rest>
117 static bool WriteVariant(json &node, uint32_t step, const _InTp &input);
118 API_EXPORT static const json &GetSubNode(const json &node, const std::string &name);
119 };
120
121 template<typename T>
GetValue(const json & node,const std::string & name,std::vector<T> & values)122 bool Serializable::GetValue(const json &node, const std::string &name, std::vector<T> &values)
123 {
124 auto &subNode = GetSubNode(node, name);
125 if (subNode.is_null() || !subNode.is_array()) {
126 return false;
127 }
128 bool result = true;
129 values.resize(subNode.size());
130 for (size_type i = 0; i < subNode.size(); ++i) {
131 result = GetValue(subNode[i], "", values[i]) && result;
132 }
133 return result;
134 }
135
136 template<typename T>
SetValue(json & node,const std::vector<T> & values)137 bool Serializable::SetValue(json &node, const std::vector<T> &values)
138 {
139 bool result = true;
140 size_type i = 0;
141 node = json::value_t::array;
142 for (const auto &value : values) {
143 result = SetValue(node[i], value) && result;
144 i++;
145 }
146 return result;
147 }
148
149 template<typename T>
GetValue(const json & node,const std::string & name,std::map<std::string,T> & values)150 bool Serializable::GetValue(const json &node, const std::string &name, std::map<std::string, T> &values)
151 {
152 auto &subNode = GetSubNode(node, name);
153 if (subNode.is_null() || !subNode.is_object()) {
154 return false;
155 }
156 bool result = true;
157 for (auto object = subNode.begin(); object != subNode.end(); ++object) {
158 result = GetValue(object.value(), "", values[object.key()]) && result;
159 }
160 return result;
161 }
162
163 template<typename T>
SetValue(json & node,const std::map<std::string,T> & values)164 bool Serializable::SetValue(json &node, const std::map<std::string, T> &values)
165 {
166 bool result = true;
167 node = json::value_t::object;
168 for (const auto &[key, value] : values) {
169 result = SetValue(node[key], value) && result;
170 }
171 return result;
172 }
173
174 template<typename T>
GetValue(const json & node,const std::string & name,T * & value)175 bool Serializable::GetValue(const json &node, const std::string &name, T *&value)
176 {
177 auto &subNode = GetSubNode(node, name);
178 if (subNode.is_null()) {
179 return false;
180 }
181 value = new(std::nothrow) T();
182 if (value == nullptr) {
183 return false;
184 }
185 bool result = GetValue(subNode, "", *value);
186 if (!result) {
187 delete value;
188 value = nullptr;
189 }
190 return result;
191 }
192
193 template<typename T>
SetValue(json & node,const T * value)194 bool Serializable::SetValue(json &node, const T *value)
195 {
196 if (value == nullptr) {
197 return false;
198 }
199 return SetValue(node, *value);
200 }
201
202 template<typename... _Types>
SetValue(json & node,const std::variant<_Types...> & input)203 bool Serializable::SetValue(json &node, const std::variant<_Types...> &input)
204 {
205 bool ret = SetValue(node[GET_NAME(type)], input.index());
206 if (!ret) {
207 return ret;
208 }
209 return WriteVariant<decltype(input), _Types...>(node[GET_NAME(value)], 0, input);
210 }
211
212 template<typename... _Types>
GetValue(const json & node,const std::string & name,std::variant<_Types...> & value)213 bool Serializable::GetValue(const json &node, const std::string &name, std::variant<_Types...> &value)
214 {
215 auto &subNode = GetSubNode(node, name);
216 if (subNode.is_null()) {
217 return false;
218 }
219 uint32_t index;
220 bool ret = GetValue(subNode, GET_NAME(type), index);
221 if (!ret) {
222 return ret;
223 }
224
225 return Serializable::ReadVariant<decltype(value), _Types...>(subNode, GET_NAME(value), 0, index, value);
226 }
227
228 template<typename _InTp>
WriteVariant(json & node,uint32_t step,const _InTp & input)229 bool Serializable::WriteVariant(json &node, uint32_t step, const _InTp &input)
230 {
231 return false;
232 }
233
234 template<typename _OutTp, typename _First, typename... _Rest>
ReadVariant(const json & node,const std::string & name,uint32_t step,uint32_t index,_OutTp & output)235 bool Serializable::ReadVariant(const json &node, const std::string &name, uint32_t step, uint32_t index, _OutTp &output)
236 {
237 if (step == index) {
238 _First result;
239 if (!Serializable::GetValue(node, name, result)) {
240 return false;
241 }
242 output = result;
243 return true;
244 }
245 return Serializable::ReadVariant<_OutTp, _Rest...>(node, name, step + 1, index, output);
246 }
247
248 template<typename _InTp, typename _First, typename... _Rest>
WriteVariant(json & node,uint32_t step,const _InTp & input)249 bool Serializable::WriteVariant(json &node, uint32_t step, const _InTp &input)
250 {
251 if (step == input.index()) {
252 return Serializable::SetValue(node, std::get<_First>(input));
253 }
254 return WriteVariant<_InTp, _Rest...>(node, step + 1, input);
255 }
256
257 template<typename _OutTp>
ReadVariant(const json & node,const std::string & name,uint32_t step,uint32_t index,_OutTp & output)258 bool Serializable::ReadVariant(const json &node, const std::string &name, uint32_t step, uint32_t index, _OutTp &output)
259 {
260 return false;
261 }
262 } // namespace DistributedData
263 } // namespace OHOS
264 #endif // OHOS_DISTRIBUTED_DATA_FRAMEWORKS_COMMON_SERIALIZABLE_H
265