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