1 /*
2 * Copyright (c) 2023 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 JSON_UTILS_H
17 #define JSON_UTILS_H
18 
19 #include <algorithm>
20 #include <functional>
21 #include <string>
22 
23 #include "nlohmann/json.hpp"
24 
25 #include "update_define.h"
26 
27 namespace OHOS::UpdateEngine {
28 enum class JsonParseError {
29     ERR_OK = 0,
30     COMMOM_ERROR,
31     MISSING_PROP,
32     TYPE_ERROR
33 };
34 
35 // 开发人员请使用该工具类封装的安全函数来获取json对象/数组,以及从json对象获取Value
36 // 当前获取json对象/数组的封装使用的parse方法参数:string输入、无解析回调、解析失败不报异常
37 class JsonUtils {
38 public:
39     template <typename T>
GetValueAndSetTo(const nlohmann::json & jsonObject,const std::string & key,T & value)40     static int32_t GetValueAndSetTo(const nlohmann::json &jsonObject, const std::string &key, T &value)
41     {
42         if (jsonObject.find(key) == jsonObject.end()) {
43             return CAST_INT(JsonParseError::MISSING_PROP);
44         }
45         if (!CheckType(jsonObject.at(key), value)) {
46             return CAST_INT(JsonParseError::TYPE_ERROR);
47         }
48         GetValue(jsonObject, key, value);
49         return CAST_INT(JsonParseError::ERR_OK);
50     }
51 
ParseAndGetJsonObject(const std::string & jsonStr,nlohmann::json & root)52     static bool ParseAndGetJsonObject(const std::string &jsonStr, nlohmann::json &root)
53     {
54         root = nlohmann::json::parse(jsonStr, nullptr, false);
55         if (root.is_discarded() || !root.is_object()) {
56             return false;
57         }
58         return true;
59     }
60 
ParseAndGetJsonArray(const std::string & jsonStr,nlohmann::json & root)61     static bool ParseAndGetJsonArray(const std::string &jsonStr, nlohmann::json &root)
62     {
63         root = nlohmann::json::parse(jsonStr, nullptr, false);
64         if (root.is_discarded() || !root.is_array()) {
65             return false;
66         }
67         return true;
68     }
69 
GetValueAndSetToArray(const nlohmann::json & jsonObject,const std::string & key,nlohmann::json & value)70     static int32_t GetValueAndSetToArray(const nlohmann::json &jsonObject, const std::string &key,
71         nlohmann::json &value)
72     {
73         if (jsonObject.find(key) == jsonObject.end()) {
74             return CAST_INT(JsonParseError::MISSING_PROP);
75         }
76         if (!jsonObject.at(key).is_array()) {
77             return CAST_INT(JsonParseError::TYPE_ERROR);
78         }
79         jsonObject.at(key).get_to(value);
80         return CAST_INT(JsonParseError::ERR_OK);
81     }
82 
SetJsonToVector(nlohmann::json & jsonObject,std::vector<std::string> & vector)83     static void SetJsonToVector(nlohmann::json &jsonObject, std::vector<std::string> &vector)
84     {
85         if (jsonObject.is_array()) {
86             for (nlohmann::json::iterator it = jsonObject.begin(); it != jsonObject.end(); ++it) {
87                 if (!it.value().is_string()) {
88                     continue;
89                 }
90                 vector.push_back(static_cast<std::string>(it.value()));
91             }
92         }
93     }
94 
SetJsonToVector(const nlohmann::json & jsonObject,const std::string & key,std::vector<std::string> & vector)95     static void SetJsonToVector(const nlohmann::json &jsonObject, const std::string &key,
96         std::vector<std::string> &vector)
97     {
98         if (!IsArray(jsonObject, key)) {
99             return;
100         }
101         nlohmann::json jsonArray = jsonObject.at(key);
102         SetJsonToVector(jsonArray, vector);
103     }
104 
IsArray(const nlohmann::json & jsonObject,const std::string & key)105     static bool IsArray(const nlohmann::json &jsonObject, const std::string &key)
106     {
107         if (jsonObject.find(key) == jsonObject.end()) {
108             return false;
109         }
110         return jsonObject.at(key).is_array();
111     }
112 
StructToJsonStr(const T & value)113     template <typename T> static std::string StructToJsonStr(const T &value)
114     {
115         nlohmann::json jsonObj(value);
116         return jsonObj.dump();
117     }
118 
JsonStrToStruct(const std::string & jsonStr,T & value)119     template <typename T> static int32_t JsonStrToStruct(const std::string &jsonStr, T &value)
120     {
121         if (jsonStr.empty()) {
122             return CAST_INT(JsonParseError::COMMOM_ERROR);
123         }
124         nlohmann::json jsonObj = nlohmann::json::parse(jsonStr, nullptr, false);
125         if (!jsonObj.is_discarded() && CheckType(jsonObj, value)) {
126             value = jsonObj.get<T>();
127             return CAST_INT(JsonParseError::ERR_OK);
128         }
129         return CAST_INT(JsonParseError::TYPE_ERROR);
130     }
131 
132 private:
CheckType(const nlohmann::json & jsonObject,std::string & value)133     static bool CheckType(const nlohmann::json &jsonObject, std::string &value)
134     {
135         return jsonObject.is_string();
136     }
137 
CheckType(const nlohmann::json & jsonObject,int32_t & value)138     static bool CheckType(const nlohmann::json &jsonObject, int32_t &value)
139     {
140         return jsonObject.is_number();
141     }
142 
CheckType(const nlohmann::json & jsonObject,uint32_t & value)143     static bool CheckType(const nlohmann::json &jsonObject, uint32_t &value)
144     {
145         return jsonObject.is_number();
146     }
147 
CheckType(const nlohmann::json & jsonObject,uint64_t & value)148     static bool CheckType(const nlohmann::json &jsonObject, uint64_t &value)
149     {
150         return jsonObject.is_number();
151     }
152 
CheckType(const nlohmann::json & jsonObject,int64_t & value)153     static bool CheckType(const nlohmann::json &jsonObject, int64_t &value)
154     {
155         return jsonObject.is_number();
156     }
157 
CheckType(const nlohmann::json & jsonObject,double & value)158     static bool CheckType(const nlohmann::json &jsonObject, double &value)
159     {
160         return jsonObject.is_number();
161     }
162 
CheckType(const nlohmann::json & jsonObject,bool & value)163     static bool CheckType(const nlohmann::json &jsonObject, bool &value)
164     {
165         return jsonObject.is_boolean();
166     }
167 
CheckType(const nlohmann::json & jsonObject,T & value)168     template <typename T> static bool CheckType(const nlohmann::json &jsonObject, T &value)
169     {
170         return jsonObject.is_object();
171     }
172 
CheckType(const nlohmann::json & jsonObject,std::vector<T> & value)173     template <typename T> static bool CheckType(const nlohmann::json &jsonObject, std::vector<T> &value)
174     {
175         return jsonObject.is_array();
176     }
177 
GetValue(const nlohmann::json & jsonObject,const std::string & key,T & value)178     template <typename T> static void GetValue(const nlohmann::json &jsonObject, const std::string &key, T &value)
179     {
180         jsonObject.at(key).get_to(value);
181     }
182 
GetValue(const nlohmann::json & jsonObject,const std::string & key,std::vector<std::string> & value)183     static void GetValue(const nlohmann::json &jsonObject, const std::string &key, std::vector<std::string> &value)
184     {
185         if (!IsArray(jsonObject, key)) {
186             return;
187         }
188         nlohmann::json jsonArray = jsonObject.at(key);
189         for (nlohmann::json::iterator it = jsonArray.begin(); it != jsonArray.end(); ++it) {
190             if (!it.value().is_string()) {
191                 continue;
192             }
193             value.push_back(static_cast<std::string>(it.value()));
194         }
195     }
196 };
197 } // namespace OHOS::UpdateEngine
198 #endif // JSON_UTILS_H