1 /*
2  * Copyright (c) 2024 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_JSON_UTIL_H
17 #define OHOS_DISTRIBUTED_JSON_UTIL_H
18 
19 #include <string>
20 
21 #include "appexecfwk_errors.h"
22 #include "bundle_constants.h"
23 #include "hilog_wrapper.h"
24 #include "json_serializer.h"
25 
26 namespace OHOS {
27 namespace DistributedSchedule {
28 enum class JsonType {
29     NULLABLE,
30     BOOLEAN,
31     NUMBER,
32     OBJECT,
33     ARRAY,
34     STRING,
35 };
36 
37 enum class ArrayType {
38     NUMBER,
39     OBJECT,
40     STRING,
41     NOT_ARRAY,
42 };
43 
44 template<typename T, typename dataType>
CheckArrayType(const nlohmann::json & jsonObject,const std::string & key,dataType & data,ArrayType arrayType,int32_t & parseResult)45 void CheckArrayType(
46     const nlohmann::json &jsonObject, const std::string &key, dataType &data, ArrayType arrayType, int32_t &parseResult)
47 {
48     auto arrays = jsonObject.at(key);
49     if (arrays.empty()) {
50         return;
51     }
52     if (arrays.size() > AppExecFwk::Constants::MAX_JSON_ARRAY_LENGTH) {
53         parseResult = ERR_APPEXECFWK_PARSE_PROFILE_PROP_SIZE_CHECK_ERROR;
54         return;
55     }
56     switch (arrayType) {
57         case ArrayType::STRING:
58             for (const auto &array : arrays) {
59                 if (!array.is_string()) {
60                     parseResult = ERR_APPEXECFWK_PARSE_PROFILE_PROP_TYPE_ERROR;
61                 }
62             }
63             if (parseResult == ERR_OK) {
64                 data = jsonObject.at(key).get<T>();
65             }
66             break;
67         case ArrayType::OBJECT:
68             for (const auto &array : arrays) {
69                 if (!array.is_object()) {
70                     parseResult = ERR_APPEXECFWK_PARSE_PROFILE_PROP_TYPE_ERROR;
71                     break;
72                 }
73             }
74             if (parseResult == ERR_OK) {
75                 data = jsonObject.at(key).get<T>();
76             }
77             break;
78         case ArrayType::NUMBER:
79             for (const auto &array : arrays) {
80                 if (!array.is_number()) {
81                     parseResult = ERR_APPEXECFWK_PARSE_PROFILE_PROP_TYPE_ERROR;
82                 }
83             }
84             if (parseResult == ERR_OK) {
85                 data = jsonObject.at(key).get<T>();
86             }
87             break;
88         case ArrayType::NOT_ARRAY:
89             HILOG_DEBUG("array %{public}s is not string type", key.c_str());
90             break;
91         default:
92             HILOG_DEBUG("array %{public}s type error", key.c_str());
93             break;
94     }
95 }
96 
97 template<typename T, typename dataType>
GetValueIfFindKey(const nlohmann::json & jsonObject,const nlohmann::detail::iter_impl<const nlohmann::json> & end,const std::string & key,dataType & data,JsonType jsonType,bool isNecessary,int32_t & parseResult,ArrayType arrayType)98 void GetValueIfFindKey(const nlohmann::json &jsonObject, const nlohmann::detail::iter_impl<const nlohmann::json> &end,
99     const std::string &key, dataType &data, JsonType jsonType, bool isNecessary, int32_t &parseResult,
100     ArrayType arrayType)
101 {
102     if (parseResult) {
103         return;
104     }
105     if (jsonObject.find(key) != end) {
106         switch (jsonType) {
107             case JsonType::BOOLEAN:
108                 if (!jsonObject.at(key).is_boolean()) {
109                     HILOG_DEBUG("type is error %{public}s is not boolean", key.c_str());
110                     parseResult = ERR_APPEXECFWK_PARSE_PROFILE_PROP_TYPE_ERROR;
111                     break;
112                 }
113                 data = jsonObject.at(key).get<T>();
114                 break;
115             case JsonType::NUMBER:
116                 if (!jsonObject.at(key).is_number()) {
117                     HILOG_DEBUG("type is error %{public}s is not number", key.c_str());
118                     parseResult = ERR_APPEXECFWK_PARSE_PROFILE_PROP_TYPE_ERROR;
119                     break;
120                 }
121                 data = jsonObject.at(key).get<T>();
122                 break;
123             case JsonType::OBJECT:
124                 if (!jsonObject.at(key).is_object()) {
125                     HILOG_DEBUG("type is error %{public}s is not object", key.c_str());
126                     parseResult = ERR_APPEXECFWK_PARSE_PROFILE_PROP_TYPE_ERROR;
127                     break;
128                 }
129                 data = jsonObject.at(key).get<T>();
130                 break;
131             case JsonType::ARRAY:
132                 if (!jsonObject.at(key).is_array()) {
133                     HILOG_DEBUG("type is error %{public}s is not array", key.c_str());
134                     parseResult = ERR_APPEXECFWK_PARSE_PROFILE_PROP_TYPE_ERROR;
135                     break;
136                 }
137                 CheckArrayType<T>(jsonObject, key, data, arrayType, parseResult);
138                 break;
139             case JsonType::STRING:
140                 if (!jsonObject.at(key).is_string()) {
141                     HILOG_DEBUG("type is error %{public}s is not string", key.c_str());
142                     parseResult = ERR_APPEXECFWK_PARSE_PROFILE_PROP_TYPE_ERROR;
143                     break;
144                 }
145                 data = jsonObject.at(key).get<T>();
146                 if (jsonObject.at(key).get<std::string>().length() > AppExecFwk::Constants::MAX_JSON_ELEMENT_LENGTH) {
147                     parseResult = ERR_APPEXECFWK_PARSE_PROFILE_PROP_SIZE_CHECK_ERROR;
148                 }
149                 break;
150             case JsonType::NULLABLE:
151                 HILOG_DEBUG("type is error %{public}s is nullable", key.c_str());
152                 break;
153             default:
154                 HILOG_DEBUG("type is error %{public}s is not jsonType", key.c_str());
155                 parseResult = ERR_APPEXECFWK_PARSE_PROFILE_PROP_TYPE_ERROR;
156         }
157         return;
158     }
159     if (isNecessary) {
160         HILOG_DEBUG("profile prop %{public}s is mission", key.c_str());
161         parseResult = ERR_APPEXECFWK_PARSE_PROFILE_MISSING_PROP;
162     }
163 }
164 
165 template<typename T>
GetJsonStrFromInfo(T & t)166 const std::string GetJsonStrFromInfo(T &t)
167 {
168     nlohmann::json json = t;
169     return json.dump();
170 }
171 
172 template<typename T>
ParseInfoFromJsonStr(const char * data,T & t)173 bool ParseInfoFromJsonStr(const char *data, T &t)
174 {
175     if (data == nullptr) {
176         HILOG_DEBUG("%{public}s failed due to data is nullptr", __func__);
177         return false;
178     }
179 
180     nlohmann::json jsonObject = nlohmann::json::parse(data, nullptr, false);
181     if (jsonObject.is_discarded()) {
182         HILOG_DEBUG("%{public}s failed due to data is discarded", __func__);
183         return false;
184     }
185 
186     t = jsonObject.get<T>();
187     return true;
188 }
189 } // namespace DistributedSchedule
190 } // namespace OHOS
191 #endif // OHOS_DISTRIBUTED_JSON_UTIL_H