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, uint16_t &value);
62 API_EXPORT static bool GetValue(const json &node, const std::string &name, bool &value);
63 API_EXPORT static bool GetValue(const json &node, const std::string &name, std::vector<uint8_t> &value);
64 API_EXPORT static bool GetValue(const json &node, const std::string &name, Serializable &value);
65 API_EXPORT static bool GetValue(const json &node, const std::string &name, double &value);
66 API_EXPORT static bool SetValue(json &node, const std::string &value);
67 API_EXPORT static bool SetValue(json &node, const uint32_t &value);
68 API_EXPORT static bool SetValue(json &node, const int32_t &value);
69 API_EXPORT static bool SetValue(json &node, const int64_t &value);
70 API_EXPORT static bool SetValue(json &node, const double &value);
71 API_EXPORT static bool SetValue(json &node, const uint64_t &value);
72 API_EXPORT static bool SetValue(json &node, const uint16_t &value);
73 // Use bool & to forbid the const T * auto convert to bool, const bool will convert to const uint32_t &value;
74 template<typename T>
SetValueSerializable75 API_EXPORT static std::enable_if_t<std::is_same_v<T, bool>, bool> SetValue(json &node, const T &value)
76 {
77 node = static_cast<bool>(value);
78 return true;
79 }
80
81 API_EXPORT static bool SetValue(json &node, const std::vector<uint8_t> &value);
82 API_EXPORT static bool SetValue(json &node, const Serializable &value);
83
84 template<typename... _Types>
85 API_EXPORT static bool SetValue(json &node, const std::variant<_Types...> &input);
86
87 template<typename... _Types>
88 API_EXPORT static bool GetValue(const json &node, const std::string &name, std::variant<_Types...> &value);
89 protected:
90 API_EXPORT ~Serializable() = default;
91
92 template<typename T>
93 static bool GetValue(const json &node, const std::string &name, std::vector<T> &values);
94
95 template<typename T>
96 static bool SetValue(json &node, const std::vector<T> &values);
97
98 template<typename T>
99 static bool GetValue(const json &node, const std::string &name, std::map<std::string, T> &values);
100
101 template<typename T>
102 static bool SetValue(json &node, const std::map<std::string, T> &values);
103
104 template<typename T>
105 static bool GetValue(const json &node, const std::string &name, T *&value);
106
107 template<typename T>
108 static bool SetValue(json &node, const T *value);
109
110 template<typename _OutTp>
111 static bool ReadVariant(const json &node, const std::string &name, uint32_t step, uint32_t index, _OutTp &output);
112
113 template<typename _OutTp, typename _First, typename... _Rest>
114 static bool ReadVariant(const json &node, const std::string &name, uint32_t step, uint32_t index, _OutTp &output);
115
116 template<typename _InTp>
117 static bool WriteVariant(json &node, uint32_t step, const _InTp &input);
118
119 template<typename _InTp, typename _First, typename... _Rest>
120 static bool WriteVariant(json &node, uint32_t step, const _InTp &input);
121 API_EXPORT static const json &GetSubNode(const json &node, const std::string &name);
122 };
123
124 template<typename T>
GetValue(const json & node,const std::string & name,std::vector<T> & values)125 bool Serializable::GetValue(const json &node, const std::string &name, std::vector<T> &values)
126 {
127 auto &subNode = GetSubNode(node, name);
128 if (subNode.is_null() || !subNode.is_array()) {
129 return false;
130 }
131 bool result = true;
132 values.resize(subNode.size());
133 for (size_type i = 0; i < subNode.size(); ++i) {
134 result = GetValue(subNode[i], "", values[i]) && result;
135 }
136 return result;
137 }
138
139 template<typename T>
SetValue(json & node,const std::vector<T> & values)140 bool Serializable::SetValue(json &node, const std::vector<T> &values)
141 {
142 bool result = true;
143 size_type i = 0;
144 node = json::value_t::array;
145 for (const auto &value : values) {
146 result = SetValue(node[i], value) && result;
147 i++;
148 }
149 return result;
150 }
151
152 template<typename T>
GetValue(const json & node,const std::string & name,std::map<std::string,T> & values)153 bool Serializable::GetValue(const json &node, const std::string &name, std::map<std::string, T> &values)
154 {
155 auto &subNode = GetSubNode(node, name);
156 if (subNode.is_null() || !subNode.is_object()) {
157 return false;
158 }
159 bool result = true;
160 for (auto object = subNode.begin(); object != subNode.end(); ++object) {
161 result = GetValue(object.value(), "", values[object.key()]) && result;
162 }
163 return result;
164 }
165
166 template<typename T>
SetValue(json & node,const std::map<std::string,T> & values)167 bool Serializable::SetValue(json &node, const std::map<std::string, T> &values)
168 {
169 bool result = true;
170 node = json::value_t::object;
171 for (const auto &[key, value] : values) {
172 result = SetValue(node[key], value) && result;
173 }
174 return result;
175 }
176
177 template<typename T>
GetValue(const json & node,const std::string & name,T * & value)178 bool Serializable::GetValue(const json &node, const std::string &name, T *&value)
179 {
180 auto &subNode = GetSubNode(node, name);
181 if (subNode.is_null()) {
182 return false;
183 }
184 value = new(std::nothrow) T();
185 if (value == nullptr) {
186 return false;
187 }
188 bool result = GetValue(subNode, "", *value);
189 if (!result) {
190 delete value;
191 value = nullptr;
192 }
193 return result;
194 }
195
196 template<typename T>
SetValue(json & node,const T * value)197 bool Serializable::SetValue(json &node, const T *value)
198 {
199 if (value == nullptr) {
200 return false;
201 }
202 return SetValue(node, *value);
203 }
204
205 template<typename... _Types>
SetValue(json & node,const std::variant<_Types...> & input)206 bool Serializable::SetValue(json &node, const std::variant<_Types...> &input)
207 {
208 bool ret = SetValue(node[GET_NAME(type)], input.index());
209 if (!ret) {
210 return ret;
211 }
212 return WriteVariant<decltype(input), _Types...>(node[GET_NAME(value)], 0, input);
213 }
214
215 template<typename... _Types>
GetValue(const json & node,const std::string & name,std::variant<_Types...> & value)216 bool Serializable::GetValue(const json &node, const std::string &name, std::variant<_Types...> &value)
217 {
218 auto &subNode = GetSubNode(node, name);
219 if (subNode.is_null()) {
220 return false;
221 }
222 uint32_t index;
223 bool ret = GetValue(subNode, GET_NAME(type), index);
224 if (!ret) {
225 return ret;
226 }
227
228 return Serializable::ReadVariant<decltype(value), _Types...>(subNode, GET_NAME(value), 0, index, value);
229 }
230
231 template<typename _InTp>
WriteVariant(json & node,uint32_t step,const _InTp & input)232 bool Serializable::WriteVariant(json &node, uint32_t step, const _InTp &input)
233 {
234 return false;
235 }
236
237 template<typename _OutTp, typename _First, typename... _Rest>
ReadVariant(const json & node,const std::string & name,uint32_t step,uint32_t index,_OutTp & output)238 bool Serializable::ReadVariant(const json &node, const std::string &name, uint32_t step, uint32_t index, _OutTp &output)
239 {
240 if (step == index) {
241 _First result;
242 if (!Serializable::GetValue(node, name, result)) {
243 return false;
244 }
245 output = result;
246 return true;
247 }
248 return Serializable::ReadVariant<_OutTp, _Rest...>(node, name, step + 1, index, output);
249 }
250
251 template<typename _InTp, typename _First, typename... _Rest>
WriteVariant(json & node,uint32_t step,const _InTp & input)252 bool Serializable::WriteVariant(json &node, uint32_t step, const _InTp &input)
253 {
254 if (step == input.index()) {
255 return Serializable::SetValue(node, std::get<_First>(input));
256 }
257 return WriteVariant<_InTp, _Rest...>(node, step + 1, input);
258 }
259
260 template<typename _OutTp>
ReadVariant(const json & node,const std::string & name,uint32_t step,uint32_t index,_OutTp & output)261 bool Serializable::ReadVariant(const json &node, const std::string &name, uint32_t step, uint32_t index, _OutTp &output)
262 {
263 return false;
264 }
265 } // namespace DistributedData
266 } // namespace OHOS
267 #endif // OHOS_DISTRIBUTED_DATA_FRAMEWORKS_COMMON_SERIALIZABLE_H
268