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