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 #include "softbus_adapter_json.h"
17 
18 #include <vector>
19 
20 #include "comm_log.h"
21 #include "nlohmann/json.hpp"
22 #include "securec.h"
23 #include "softbus_adapter_mem.h"
24 
25 
JSON_CreateObject(void)26 JsonObj *JSON_CreateObject(void)
27 {
28     JsonObj *obj = new (std::nothrow) JsonObj();
29     if (obj == nullptr) {
30         COMM_LOGE(COMM_ADAPTER, "new JsonObj fail");
31         return nullptr;
32     }
33     nlohmann::json *json = new (std::nothrow) nlohmann::json();
34     if (json == nullptr) {
35         COMM_LOGE(COMM_ADAPTER, "new nlohmann fail");
36         delete obj;
37         obj = nullptr;
38         return nullptr;
39     }
40     obj->context = reinterpret_cast<void *>(json);
41     return obj;
42 }
43 
JSON_Delete(JsonObj * obj)44 void JSON_Delete(JsonObj *obj)
45 {
46     if (obj == nullptr) {
47         return;
48     }
49     if (obj->context != nullptr) {
50         nlohmann::json *json = reinterpret_cast<nlohmann::json *>(obj->context);
51         if (json != nullptr) {
52             delete json;
53         }
54         obj->context = nullptr;
55     }
56     delete obj;
57     obj = nullptr;
58 }
59 
JSON_Free(void * obj)60 void JSON_Free(void *obj)
61 {
62     if (obj != nullptr) {
63         SoftBusFree(obj);
64     }
65 }
66 
JSON_PrintUnformatted(const JsonObj * obj)67 char *JSON_PrintUnformatted(const JsonObj *obj)
68 {
69     if (obj == nullptr) {
70         COMM_LOGE(COMM_ADAPTER, "invalid param");
71         return nullptr;
72     }
73     nlohmann::json *json = reinterpret_cast<nlohmann::json *>(obj->context);
74     if (json == nullptr) {
75         COMM_LOGE(COMM_ADAPTER, "invaild json param");
76         return nullptr;
77     }
78     std::string jsonString = json->dump();
79 
80     char *result = (char *)SoftBusCalloc(jsonString.length() + 1); /* 1 for '\0' */
81     if (result == nullptr) {
82         COMM_LOGE(COMM_ADAPTER, "malloc array fail");
83         return nullptr;
84     }
85     if (strcpy_s(result, jsonString.length() + 1, jsonString.c_str()) != EOK) {
86         COMM_LOGE(COMM_ADAPTER, "strcpy json string fail");
87         SoftBusFree(result);
88         return nullptr;
89     }
90     return result;
91 }
92 
JSON_Parse(const char * str,uint32_t len)93 JsonObj *JSON_Parse(const char *str, uint32_t len)
94 {
95     JsonObj *obj = JSON_CreateObject();
96     if (obj == nullptr) {
97         COMM_LOGE(COMM_ADAPTER, "create json object fail");
98         return nullptr;
99     }
100     nlohmann::json *json = reinterpret_cast<nlohmann::json *>(obj->context);
101     if (json == nullptr) {
102         JSON_Delete(obj);
103         COMM_LOGE(COMM_ADAPTER, "cast json fail");
104         return nullptr;
105     }
106     std::string jsonString(str, len);
107     nlohmann::json entity = nlohmann::json::parse(jsonString, nullptr, false);
108     if (entity.is_discarded()) {
109         JSON_Delete(obj);
110         COMM_LOGE(COMM_ADAPTER, "parse json fail");
111         return nullptr;
112     }
113     for (auto &item : entity.items()) {
114         (*json)[item.key()] = item.value();
115     }
116     return obj;
117 }
118 
JSON_AddBoolToObject(JsonObj * obj,const char * key,bool value)119 bool JSON_AddBoolToObject(JsonObj *obj, const char *key, bool value)
120 {
121     if (obj == nullptr || key == nullptr) {
122         COMM_LOGE(COMM_ADAPTER, "invalid param");
123         return false;
124     }
125     nlohmann::json *json = reinterpret_cast<nlohmann::json *>(obj->context);
126     if (json == nullptr) {
127         COMM_LOGE(COMM_ADAPTER, "invaild json param");
128         return false;
129     }
130     (*json)[key] = value;
131     return true;
132 }
133 
JSON_GetBoolFromOject(const JsonObj * obj,const char * key,bool * value)134 bool JSON_GetBoolFromOject(const JsonObj *obj, const char *key, bool *value)
135 {
136     if (obj == nullptr || key == nullptr || value == nullptr) {
137         COMM_LOGE(COMM_ADAPTER, "invalid param");
138         return false;
139     }
140     nlohmann::json *json = reinterpret_cast<nlohmann::json *>(obj->context);
141     if (json == nullptr) {
142         COMM_LOGE(COMM_ADAPTER, "invaild json param");
143         return false;
144     }
145     nlohmann::json item = (*json)[key];
146     if (!item.is_boolean()) {
147         COMM_LOGE(COMM_ADAPTER, "Cannot find or invalid key. key=%{public}s", key);
148         return false;
149     }
150     *value = item.get<bool>();
151     return true;
152 }
153 
154 template <typename Integer>
JSON_AddIntegerToObject(JsonObj * obj,const char * key,Integer num)155 static bool JSON_AddIntegerToObject(JsonObj *obj, const char *key, Integer num)
156 {
157     if (obj == nullptr || key == nullptr) {
158         COMM_LOGE(COMM_ADAPTER, "invalid param");
159         return false;
160     }
161     nlohmann::json *json = reinterpret_cast<nlohmann::json *>(obj->context);
162     if (json == nullptr) {
163         COMM_LOGE(COMM_ADAPTER, "invaild json param");
164         return false;
165     }
166     (*json)[key] = num;
167     return true;
168 }
169 
170 template <typename Integer>
JSON_GetIntegerFromObject(const JsonObj * obj,const char * key,Integer & value)171 static bool JSON_GetIntegerFromObject(const JsonObj *obj, const char *key, Integer &value)
172 {
173     if (obj == nullptr || key == nullptr) {
174         COMM_LOGE(COMM_ADAPTER, "invalid param");
175         return false;
176     }
177     nlohmann::json *json = reinterpret_cast<nlohmann::json *>(obj->context);
178     if (json == nullptr) {
179         COMM_LOGE(COMM_ADAPTER, "invaild json param");
180         return false;
181     }
182     nlohmann::json item = (*json)[key];
183     if (!item.is_number()) {
184         COMM_LOGE(COMM_ADAPTER, "Cannot find or invalid key. key=%{public}s", key);
185         return false;
186     }
187     value = item.get<Integer>();
188     return true;
189 }
190 
JSON_AddInt16ToObject(JsonObj * obj,const char * key,int16_t value)191 bool JSON_AddInt16ToObject(JsonObj *obj, const char *key, int16_t value)
192 {
193     return JSON_AddIntegerToObject(obj, key, value);
194 }
195 
JSON_GetInt16FromOject(const JsonObj * obj,const char * key,int16_t * value)196 bool JSON_GetInt16FromOject(const JsonObj *obj, const char *key, int16_t *value)
197 {
198     if (value == nullptr) {
199         COMM_LOGE(COMM_ADAPTER, "invalid param");
200         return false;
201     }
202     return JSON_GetIntegerFromObject(obj, key, *value);
203 }
204 
JSON_AddInt32ToObject(JsonObj * obj,const char * key,int32_t value)205 bool JSON_AddInt32ToObject(JsonObj *obj, const char *key, int32_t value)
206 {
207     return JSON_AddIntegerToObject(obj, key, value);
208 }
209 
JSON_GetInt32FromOject(const JsonObj * obj,const char * key,int32_t * value)210 bool JSON_GetInt32FromOject(const JsonObj *obj, const char *key, int32_t *value)
211 {
212     if (value == nullptr) {
213         COMM_LOGE(COMM_ADAPTER, "invalid param");
214         return false;
215     }
216     return JSON_GetIntegerFromObject(obj, key, *value);
217 }
218 
JSON_AddInt64ToObject(JsonObj * obj,const char * key,int64_t value)219 bool JSON_AddInt64ToObject(JsonObj *obj, const char *key, int64_t value)
220 {
221     return JSON_AddIntegerToObject(obj, key, value);
222 }
223 
JSON_GetInt64FromOject(const JsonObj * obj,const char * key,int64_t * value)224 bool JSON_GetInt64FromOject(const JsonObj *obj, const char *key, int64_t *value)
225 {
226     if (value == nullptr) {
227         COMM_LOGE(COMM_ADAPTER, "invalid param");
228         return false;
229     }
230     return JSON_GetIntegerFromObject(obj, key, *value);
231 }
232 
JSON_AddStringToObject(JsonObj * obj,const char * key,const char * value)233 bool JSON_AddStringToObject(JsonObj *obj, const char *key, const char *value)
234 {
235     if (obj == nullptr || key == nullptr || value == nullptr) {
236         COMM_LOGE(COMM_ADAPTER, "invalid param");
237         return false;
238     }
239     nlohmann::json *json = reinterpret_cast<nlohmann::json *>(obj->context);
240     if (json == nullptr) {
241         COMM_LOGE(COMM_ADAPTER, "invaild json param");
242         return false;
243     }
244     (*json)[key] = std::string(value);
245     return true;
246 }
247 
JSON_GetStringFromOject(const JsonObj * obj,const char * key,char * value,uint32_t size)248 bool JSON_GetStringFromOject(const JsonObj *obj, const char *key, char *value, uint32_t size)
249 {
250     if (obj == nullptr || key == nullptr || value == nullptr) {
251         COMM_LOGE(COMM_ADAPTER, "invalid param");
252         return false;
253     }
254     nlohmann::json *json = reinterpret_cast<nlohmann::json *>(obj->context);
255     if (json == nullptr) {
256         COMM_LOGE(COMM_ADAPTER, "invaild json param");
257         return false;
258     }
259     nlohmann::json item = (*json)[key];
260     if (!item.is_string()) {
261         COMM_LOGD(COMM_ADAPTER, "cannot find or invalid key. key=%{public}s", key);
262         return false;
263     }
264     std::string valueString = item.get<std::string>();
265     if (strcpy_s(value, size, valueString.c_str()) != EOK) {
266         COMM_LOGE(COMM_ADAPTER, "strcpy value err, key=%{public}s, size=%{public}u, value=%{public}s",
267             key, size, valueString.c_str());
268         return false;
269     }
270     return true;
271 }
272 
JSON_AddStringArrayToObject(JsonObj * obj,const char * key,const char ** value,int32_t len)273 bool JSON_AddStringArrayToObject(JsonObj *obj, const char *key, const char **value, int32_t len)
274 {
275     if (value == nullptr || obj == nullptr || key == nullptr || len <= 0) {
276         COMM_LOGE(COMM_ADAPTER, "input invalid");
277         return false;
278     }
279     nlohmann::json *json = reinterpret_cast<nlohmann::json *>(obj->context);
280     if (json == nullptr) {
281         COMM_LOGE(COMM_ADAPTER, "invaild json param");
282         return false;
283     }
284     nlohmann::json valueStringArray = nlohmann::json::array();
285     for (int32_t i = 0; i < len; i++) {
286         valueStringArray.push_back(value[i]);
287     }
288     (*json)[key] = valueStringArray;
289     return true;
290 }
291 
JSON_GetStringArrayFromOject(const JsonObj * obj,const char * key,char ** value,int32_t * len)292 bool JSON_GetStringArrayFromOject(const JsonObj *obj, const char *key, char **value, int32_t *len)
293 {
294     if (value == nullptr || obj == nullptr || key == nullptr || len == nullptr || *len <= 0) {
295         COMM_LOGE(COMM_ADAPTER, "input invalid");
296         return false;
297     }
298     nlohmann::json *json = reinterpret_cast<nlohmann::json *>(obj->context);
299     if (json == nullptr) {
300         COMM_LOGE(COMM_ADAPTER, "invaild json param");
301         return false;
302     }
303     nlohmann::json item = (*json)[key];
304     if (!item.is_array()) {
305         COMM_LOGE(COMM_ADAPTER, "cannot find or invalid key. key=%{public}s", key);
306         return false;
307     }
308     if ((unsigned long)(*len) < (unsigned long)item.size()) {
309         COMM_LOGE(COMM_ADAPTER, "item size invalid, size=%{public}lu.", (unsigned long)item.size());
310         return false;
311     }
312     int32_t i = 0;
313     for (nlohmann::json::iterator it = item.begin(); it != item.end(); ++it) {
314         std::string str = it.value().get<std::string>();
315         const char *valueString = str.c_str();
316         uint32_t valueLen = strlen(valueString) + 1;
317         value[i] = reinterpret_cast<char *>(SoftBusCalloc(valueLen));
318         if (value[i] == nullptr) {
319             return false;
320         }
321         if (strcpy_s(value[i], valueLen, valueString) != EOK) {
322             COMM_LOGE(COMM_ADAPTER, "strcpy value err. key=%{public}s, value=%{public}s", key, valueString);
323             return false;
324         }
325         i++;
326     }
327     *len = item.size();
328     return true;
329 }
330 
JSON_AddBytesToObject(JsonObj * obj,const char * key,uint8_t * value,uint32_t size)331 bool JSON_AddBytesToObject(JsonObj *obj, const char *key, uint8_t *value, uint32_t size)
332 {
333     if (obj == nullptr || key == nullptr || value == nullptr || size == 0) {
334         COMM_LOGE(COMM_ADAPTER, "input invalid");
335         return false;
336     }
337     std::vector<uint8_t> bytes(value, value + size);
338     nlohmann::json *json = reinterpret_cast<nlohmann::json *>(obj->context);
339     if (json == nullptr) {
340         COMM_LOGE(COMM_ADAPTER, "invalid json param");
341         return false;
342     }
343     (*json)[key] = bytes;
344     return true;
345 }
346 
JSON_GetBytesFromObject(const JsonObj * obj,const char * key,uint8_t * value,uint32_t bufLen,uint32_t * size)347 bool JSON_GetBytesFromObject(const JsonObj *obj, const char *key, uint8_t *value, uint32_t bufLen, uint32_t *size)
348 {
349     if (obj == nullptr || key == nullptr || value == nullptr || bufLen == 0 || size == nullptr) {
350         COMM_LOGE(COMM_ADAPTER, "input invalid");
351         return false;
352     }
353     nlohmann::json *json = reinterpret_cast<nlohmann::json *>(obj->context);
354     if (json == nullptr) {
355         COMM_LOGE(COMM_ADAPTER, "invaild json param");
356         return false;
357     }
358     if (json->count(key) <= 0) {
359         COMM_LOGE(COMM_ADAPTER, "key does not exist");
360         return false;
361     }
362     std::vector<uint8_t> bytes = (*json)[key];
363     if (bufLen < bytes.size()) {
364         COMM_LOGE(COMM_ADAPTER, "item size invalid, size=%{public}zu", bytes.size());
365         return false;
366     }
367     if (memcpy_s(value, bufLen, bytes.data(), bytes.size()) != EOK) {
368         COMM_LOGE(COMM_ADAPTER, "memcpy fail");
369         return false;
370     }
371     *size = bytes.size();
372     return true;
373 }