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