1 /*
2  * Copyright (c) 2021-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 #include "softbus_json_utils.h"
17 
18 #include "comm_log.h"
19 #include <securec.h>
20 
21 #include "softbus_adapter_mem.h"
22 #include "softbus_error_code.h"
23 
GetStringItemByJsonObject(const cJSON * json,const char * const string,char * target,uint32_t targetLen)24 int32_t GetStringItemByJsonObject(const cJSON *json, const char * const string, char *target,
25     uint32_t targetLen)
26 {
27     if (json == NULL || string == NULL || target == NULL) {
28         COMM_LOGE(COMM_UTILS, "invalid param");
29         return SOFTBUS_INVALID_PARAM;
30     }
31     cJSON *item = cJSON_GetObjectItemCaseSensitive(json, string);
32     if (item == NULL || !cJSON_IsString(item)) {
33         COMM_LOGD(COMM_UTILS, "Cannot find or invalid string. string=%{public}s", string);
34         return SOFTBUS_ERR;
35     }
36     uint32_t length = strlen(item->valuestring);
37     if (length >= targetLen) {
38         COMM_LOGE(COMM_UTILS, "the length is to long. length=%{public}d, string=%{public}s", length, string);
39         return SOFTBUS_INVALID_PARAM;
40     }
41     int32_t ret = strcpy_s(target, targetLen, item->valuestring);
42     if (ret != EOK) {
43         COMM_LOGE(COMM_UTILS, "strcpy error. ret=%{public}d", ret);
44         return SOFTBUS_ERR;
45     }
46     return SOFTBUS_OK;
47 }
48 
GetJsonObjectStringItem(const cJSON * json,const char * const string,char * target,uint32_t targetLen)49 bool GetJsonObjectStringItem(const cJSON *json, const char * const string, char *target,
50     uint32_t targetLen)
51 {
52     if (json == NULL || string == NULL || target == NULL) {
53         COMM_LOGE(COMM_UTILS, "invalid param");
54         return false;
55     }
56     cJSON *item = cJSON_GetObjectItemCaseSensitive(json, string);
57     if (item == NULL || !cJSON_IsString(item)) {
58         COMM_LOGD(COMM_UTILS, "Cannot find or invalid string. string=%{public}s", string);
59         return false;
60     }
61     uint32_t length = strlen(item->valuestring);
62     if (length >= targetLen) {
63         COMM_LOGE(COMM_UTILS, "the length is to long. length=%{public}d, string=%{public}s", length, string);
64         return false;
65     }
66     int32_t ret = strcpy_s(target, targetLen, item->valuestring);
67     if (ret != EOK) {
68         COMM_LOGE(COMM_UTILS, "strcpy error. ret=%{public}d", ret);
69         return false;
70     }
71     return true;
72 }
73 
GetJsonObjectNumberItem(const cJSON * json,const char * const string,int32_t * target)74 bool GetJsonObjectNumberItem(const cJSON *json, const char * const string, int32_t *target)
75 {
76     if (json == NULL || string == NULL || target == NULL) {
77         COMM_LOGE(COMM_UTILS, "invalid param");
78         return false;
79     }
80     cJSON *item = cJSON_GetObjectItemCaseSensitive(json, string);
81     if (item == NULL || !cJSON_IsNumber(item) || (item->valuedouble < 0)) {
82         COMM_LOGD(COMM_UTILS, "Cannot find or invalid string. string=%{public}s", string);
83         return false;
84     }
85     *target = (int32_t)item->valuedouble;
86     return true;
87 }
88 
GetJsonObjectSignedNumberItem(const cJSON * json,const char * const string,int32_t * target)89 bool GetJsonObjectSignedNumberItem(const cJSON *json, const char * const string, int32_t *target)
90 {
91     if (json == NULL || string == NULL || target == NULL) {
92         COMM_LOGE(COMM_UTILS, "invalid param");
93         return false;
94     }
95     cJSON *item = cJSON_GetObjectItemCaseSensitive(json, string);
96     if (item == NULL || !cJSON_IsNumber(item)) {
97         COMM_LOGD(COMM_UTILS, "Cannot find or invalid string. string=%{public}s", string);
98         return false;
99     }
100     *target = (int32_t)item->valuedouble;
101     return true;
102 }
103 
GetJsonObjectDoubleItem(const cJSON * json,const char * const string,double * target)104 bool GetJsonObjectDoubleItem(const cJSON *json, const char * const string, double *target)
105 {
106     if (json == NULL || string == NULL || target == NULL) {
107         COMM_LOGE(COMM_UTILS, "invalid param");
108         return false;
109     }
110     cJSON* item = cJSON_GetObjectItemCaseSensitive(json, string);
111     if (item == NULL || !cJSON_IsNumber(item)) {
112         COMM_LOGD(COMM_UTILS, "Cannot find or invalid string. string=%{public}s", string);
113         return false;
114     }
115     *target = item->valuedouble;
116     return true;
117 }
118 
GetJsonObjectNumber16Item(const cJSON * json,const char * const string,uint16_t * target)119 bool GetJsonObjectNumber16Item(const cJSON *json, const char * const string, uint16_t *target)
120 {
121     if (json == NULL || string == NULL || target == NULL) {
122         COMM_LOGE(COMM_UTILS, "invalid param");
123         return false;
124     }
125     cJSON *item = cJSON_GetObjectItemCaseSensitive(json, string);
126     if (item == NULL || !cJSON_IsNumber(item) || (item->valuedouble < 0)) {
127         COMM_LOGD(COMM_UTILS, "Cannot find or invalid string. string=%{public}s", string);
128         return false;
129     }
130     *target = (uint16_t)item->valuedouble;
131     return true;
132 }
133 
GetJsonObjectNumber64Item(const cJSON * json,const char * const string,int64_t * target)134 bool GetJsonObjectNumber64Item(const cJSON *json, const char * const string, int64_t *target)
135 {
136     if (json == NULL || string == NULL || target == NULL) {
137         COMM_LOGE(COMM_UTILS, "invalid param");
138         return false;
139     }
140     cJSON *item = cJSON_GetObjectItemCaseSensitive(json, string);
141     if (item == NULL || !cJSON_IsNumber(item) || (item->valuedouble < 0)) {
142         COMM_LOGD(COMM_UTILS, "Cannot find or invalid string. string=%{public}s", string);
143         return false;
144     }
145     *target = (int64_t)item->valuedouble;
146     return true;
147 }
148 
GetJsonObjectSignedNumber64Item(const cJSON * json,const char * const string,int64_t * target)149 bool GetJsonObjectSignedNumber64Item(const cJSON *json, const char * const string, int64_t *target)
150 {
151     if (json == NULL || string == NULL || target == NULL) {
152         COMM_LOGE(COMM_UTILS, "invalid param");
153         return false;
154     }
155     cJSON *item = cJSON_GetObjectItemCaseSensitive(json, string);
156     if (item == NULL || !cJSON_IsNumber(item)) {
157         COMM_LOGD(COMM_UTILS, "Cannot find or invalid string. string=%{public}s", string);
158         return false;
159     }
160     *target = (int64_t)item->valuedouble;
161     return true;
162 }
163 
GetJsonObjectInt32Item(const cJSON * json,const char * const string,int32_t * target)164 bool GetJsonObjectInt32Item(const cJSON *json, const char * const string, int32_t *target)
165 {
166     if (json == NULL || string == NULL || target == NULL) {
167         COMM_LOGE(COMM_UTILS, "invalid param");
168         return false;
169     }
170     cJSON *item = cJSON_GetObjectItemCaseSensitive(json, string);
171     if (item == NULL || !cJSON_IsNumber(item)) {
172         COMM_LOGD(COMM_UTILS, "Cannot find or invalid string. string=%{public}s", string);
173         return false;
174     }
175     *target = (int32_t)item->valuedouble;
176     return true;
177 }
178 
GetJsonObjectBoolItem(const cJSON * json,const char * const string,bool * target)179 bool GetJsonObjectBoolItem(const cJSON *json, const char * const string, bool *target)
180 {
181     if (json == NULL || string == NULL || target == NULL) {
182         COMM_LOGE(COMM_UTILS, "invalid param");
183         return false;
184     }
185     cJSON *item = cJSON_GetObjectItemCaseSensitive(json, string);
186     if (item == NULL || !cJSON_IsBool(item)) {
187         COMM_LOGD(COMM_UTILS, "Cannot find or invalid string. string=%{public}s", string);
188         return false;
189     }
190     *target = (bool)item->valueint;
191     return true;
192 }
193 
AddStringToJsonObject(cJSON * json,const char * const string,const char * value)194 bool AddStringToJsonObject(cJSON *json, const char * const string, const char *value)
195 {
196     if (value == NULL || json == NULL || string == NULL) {
197         COMM_LOGE(COMM_UTILS, "invalid param");
198         return false;
199     }
200     cJSON *item = cJSON_CreateString(value);
201     if (item == NULL) {
202         COMM_LOGD(COMM_UTILS, "Cannot create cJSON string object. string=%{public}s", string);
203         return false;
204     }
205     if (!cJSON_AddItemToObject(json, string, item)) {
206         cJSON_Delete(item);
207         return false;
208     }
209     return true;
210 }
211 
AddStringArrayToJsonObject(cJSON * json,const char * const string,const char * const * strings,int32_t count)212 bool AddStringArrayToJsonObject(cJSON *json, const char * const string, const char * const *strings, int32_t count)
213 {
214     COMM_CHECK_AND_RETURN_RET_LOGE(json != NULL && string != NULL && strings != NULL, false, COMM_UTILS,
215         "param is null");
216     COMM_CHECK_AND_RETURN_RET_LOGE(count > 0, false, COMM_UTILS, "count <= 0");
217 
218     cJSON *item = cJSON_CreateStringArray(strings, count);
219     if (item == NULL) {
220         COMM_LOGE(COMM_UTILS, "Cannot create cJSON string array object. string=%{public}s", string);
221         return false;
222     }
223 
224     if (!cJSON_AddItemToObject(json, string, item)) {
225         COMM_LOGE(COMM_UTILS, "Cannot add string array object to json. string=%{public}s", string);
226         cJSON_Delete(item);
227         return false;
228     }
229     return true;
230 }
231 
AddNumber16ToJsonObject(cJSON * json,const char * const string,uint16_t num)232 bool AddNumber16ToJsonObject(cJSON *json, const char * const string, uint16_t num)
233 {
234     if (json == NULL || string == NULL) {
235         COMM_LOGE(COMM_UTILS, "invalid param");
236         return false;
237     }
238     cJSON *item = cJSON_CreateNumber((double)num);
239     if (item == NULL) {
240         COMM_LOGE(COMM_UTILS, "Cannot create cJSON number object. string=%{public}s", string);
241         return false;
242     }
243     if (!cJSON_AddItemToObject(json, string, item)) {
244         COMM_LOGE(COMM_UTILS, "Cannot add num object to json. string=%{public}s", string);
245         cJSON_Delete(item);
246         return false;
247     }
248     return true;
249 }
250 
AddNumberToJsonObject(cJSON * json,const char * const string,int32_t num)251 bool AddNumberToJsonObject(cJSON *json, const char * const string, int32_t num)
252 {
253     if (json == NULL || string == NULL) {
254         COMM_LOGE(COMM_UTILS, "invalid param");
255         return false;
256     }
257     cJSON *item = cJSON_CreateNumber((double)num);
258     if (item == NULL) {
259         COMM_LOGE(COMM_UTILS, "Cannot create cJSON number object. string=%{public}s", string);
260         return false;
261     }
262     if (!cJSON_AddItemToObject(json, string, item)) {
263         COMM_LOGE(COMM_UTILS, "Cannot add num object to json. string=%{public}s", string);
264         cJSON_Delete(item);
265         return false;
266     }
267     return true;
268 }
269 
AddNumber64ToJsonObject(cJSON * json,const char * const string,int64_t num)270 bool AddNumber64ToJsonObject(cJSON *json, const char * const string, int64_t num)
271 {
272     if (json == NULL || string == NULL) {
273         COMM_LOGE(COMM_UTILS, "invalid param");
274         return false;
275     }
276     cJSON *item = cJSON_CreateNumber((double)num);
277     if (item == NULL) {
278         COMM_LOGE(COMM_UTILS, "Cannot create cJSON number object. string=%{public}s", string);
279         return false;
280     }
281     if (!cJSON_AddItemToObject(json, string, item)) {
282         COMM_LOGE(COMM_UTILS, "Cannot add num64 object to json. string=%{public}s", string);
283         cJSON_Delete(item);
284         return false;
285     }
286     return true;
287 }
288 
AddBoolToJsonObject(cJSON * json,const char * const string,bool value)289 bool AddBoolToJsonObject(cJSON *json, const char * const string, bool value)
290 {
291     if (json == NULL || string == NULL) {
292         COMM_LOGE(COMM_UTILS, "invalid param");
293         return false;
294     }
295     cJSON *item = cJSON_CreateBool(value);
296     if (item == NULL) {
297         COMM_LOGE(COMM_UTILS, "Cannot create cJSON bool object. string=%{public}s", string);
298         return false;
299     }
300     if (!cJSON_AddItemToObject(json, string, item)) {
301         COMM_LOGE(COMM_UTILS, "Cannot add bool object to json. string=%{public}s", string);
302         cJSON_Delete(item);
303         return false;
304     }
305     return true;
306 }
307 
GetDynamicStringItemByJsonObject(const cJSON * const json,const char * const string,uint32_t limit)308 char *GetDynamicStringItemByJsonObject(const cJSON * const json, const char * const string, uint32_t limit)
309 {
310     if (json == NULL || string == NULL) {
311         COMM_LOGE(COMM_UTILS, "invalid param");
312         return NULL;
313     }
314 
315     cJSON *item = cJSON_GetObjectItemCaseSensitive(json, string);
316     if (item == NULL || !cJSON_IsString(item)) {
317         COMM_LOGD(COMM_UTILS, "Cannot find or invalid string. string=%{public}s", string);
318         return NULL;
319     }
320     uint32_t length = strlen(item->valuestring);
321     if (length > limit) {
322         COMM_LOGE(COMM_UTILS,
323             "key length is large than limit. string=%{public}s, length=%{public}u, limit=%{public}u", string, length,
324             limit);
325         return NULL;
326     }
327     char *value = SoftBusCalloc(length + 1);
328     if (value == NULL) {
329         COMM_LOGE(COMM_UTILS, "malloc failed, length=%{public}u", length);
330         return NULL;
331     }
332     if (strcpy_s(value, length + 1, item->valuestring) != EOK) {
333         COMM_LOGE(COMM_UTILS, "copy failed, length=%{public}u", length);
334         SoftBusFree(value);
335         return NULL;
336     }
337     return value;
338 }
339 
AddIntArrayToJsonObject(cJSON * json,const char * string,const int32_t * array,int32_t arrayLen)340 bool AddIntArrayToJsonObject(cJSON *json, const char *string, const int32_t *array, int32_t arrayLen)
341 {
342     if (json == NULL || string == NULL || array == NULL || arrayLen <= 0) {
343         COMM_LOGE(COMM_UTILS, "invalid param");
344         return false;
345     }
346     cJSON *arrayObj = cJSON_CreateIntArray(array, arrayLen);
347     if (arrayObj == NULL) {
348         COMM_LOGE(COMM_EVENT, "Cannot create cJSON array object. string=%{public}s", string);
349         return false;
350     }
351     if (!cJSON_AddItemToObject((cJSON *)json, string, arrayObj)) {
352         cJSON_Delete(arrayObj);
353         return false;
354     }
355     return true;
356 }
357 
GetJsonObjectIntArrayItem(const cJSON * json,const char * string,int32_t * array,int32_t arrayLen)358 bool GetJsonObjectIntArrayItem(const cJSON *json, const char *string, int32_t *array, int32_t arrayLen)
359 {
360     if (json == NULL || string == NULL || array == NULL || arrayLen <= 0) {
361         COMM_LOGE(COMM_UTILS, "invalid param");
362         return false;
363     }
364     cJSON *objValue = cJSON_GetObjectItem(json, string);
365     if (objValue == NULL) {
366         COMM_LOGE(COMM_EVENT, "Cannot create cJSON objValue. string=%{public}s", string);
367         return false;
368     }
369     if (!cJSON_IsArray(objValue)) {
370         return false;
371     }
372     int32_t size = cJSON_GetArraySize(objValue);
373     if (size > arrayLen) {
374         size = arrayLen;
375     }
376     uint32_t index = 0;
377     for (int32_t i = 0; i < size; i++) {
378         cJSON *item = cJSON_GetArrayItem(objValue, i);
379         if (item == NULL) {
380             return false;
381         }
382         if (!cJSON_IsNumber(item)) {
383             continue;
384         }
385         array[index++] = item->valueint;
386     }
387     return true;
388 }
389