23#include <winpr/json.h>
24#include <winpr/assert.h>
26#if defined(WITH_CJSON)
27#include <cjson/cJSON.h>
29#if defined(WITH_JSONC)
33#if defined(WITH_CJSON)
34#if CJSON_VERSION_MAJOR == 1
35#if (CJSON_VERSION_MINOR < 7) || ((CJSON_VERSION_MINOR == 7) && (CJSON_VERSION_PATCH < 13))
36#define USE_CJSON_COMPAT
41#if defined(WITH_JSONC)
42#if JSON_C_MAJOR_VERSION == 0
43#if JSON_C_MINOR_VERSION < 14
44static struct json_object* json_object_new_null(
void)
52#if defined(USE_CJSON_COMPAT)
53static double cJSON_GetNumberValue(
const cJSON* prop)
58#define COMPAT_NAN_UNDEF
61#define COMPAT_NAN_UNDEF
65 if (!cJSON_IsNumber(prop))
67 char* val = cJSON_GetStringValue(prop);
73 double dval = strtod(val, &endptr);
82#ifdef COMPAT_NAN_UNDEF
87static cJSON* cJSON_ParseWithLength(
const char* value,
size_t buffer_length)
90 const size_t slen = strnlen(value, buffer_length);
91 if (slen >= buffer_length)
93 if (value[buffer_length] !=
'\0')
96 return cJSON_Parse(value);
102#if defined(WITH_JSONC)
103 return _snprintf(buffer, len,
"json-c %s", json_c_version());
104#elif defined(WITH_CJSON)
105 return _snprintf(buffer, len,
"cJSON %s", cJSON_Version());
107 return _snprintf(buffer, len,
"JSON support not available");
113#if defined(WITH_JSONC)
114 return json_tokener_parse(value);
115#elif defined(WITH_CJSON)
116 return cJSON_Parse(value);
125#if defined(WITH_JSONC)
126 WINPR_ASSERT(buffer_length <= INT_MAX);
127 json_tokener* tok = json_tokener_new();
130 json_object* obj = json_tokener_parse_ex(tok, value, (
int)buffer_length);
131 json_tokener_free(tok);
133#elif defined(WITH_CJSON)
134 return cJSON_ParseWithLength(value, buffer_length);
137 WINPR_UNUSED(buffer_length);
144#if defined(WITH_JSONC)
145 json_object_put((json_object*)item);
146#elif defined(WITH_CJSON)
147 cJSON_Delete((cJSON*)item);
155#if defined(WITH_JSONC)
156 return json_object_array_get_idx((
const json_object*)array, index);
157#elif defined(WITH_CJSON)
158 WINPR_ASSERT(index <= INT_MAX);
159 return cJSON_GetArrayItem((
const cJSON*)array, (INT)index);
169#if defined(WITH_JSONC)
170 return json_object_array_length((
const json_object*)array);
171#elif defined(WITH_CJSON)
172 const int rc = cJSON_GetArraySize((
const cJSON*)array);
184#if defined(WITH_JSONC)
185 return json_object_object_get((
const json_object*)
object,
string);
186#elif defined(WITH_CJSON)
187 return cJSON_GetObjectItem((
const cJSON*)
object,
string);
189 WINPR_UNUSED(
object);
190 WINPR_UNUSED(
string);
197#if defined(WITH_JSONC)
198 return json_object_object_get((
const json_object*)
object,
string);
199#elif defined(WITH_CJSON)
200 return cJSON_GetObjectItemCaseSensitive((
const cJSON*)
object,
string);
202 WINPR_UNUSED(
object);
203 WINPR_UNUSED(
string);
210#if defined(WITH_JSONC)
211 return json_object_object_get_ex((
const json_object*)
object,
string, NULL);
212#elif defined(WITH_CJSON)
213 return cJSON_HasObjectItem((
const cJSON*)
object,
string);
215 WINPR_UNUSED(
object);
216 WINPR_UNUSED(
string);
223#if defined(WITH_JSONC)
224 return json_util_get_last_err();
225#elif defined(WITH_CJSON)
226 return cJSON_GetErrorPtr();
234#if defined(WITH_JSONC)
235 return json_object_get_string((json_object*)item);
236#elif defined(WITH_CJSON)
237 return cJSON_GetStringValue((cJSON*)item);
246#if defined(WITH_JSONC)
247 return json_object_get_double((
const json_object*)item);
248#elif defined(WITH_CJSON)
249 return cJSON_GetNumberValue((
const cJSON*)item);
258#if defined(WITH_JSONC)
272#elif defined(WITH_CJSON)
273 return cJSON_IsInvalid((
const cJSON*)item);
282#if defined(WITH_JSONC)
283 if (!json_object_is_type((
const json_object*)item, json_type_boolean))
285 json_bool val = json_object_get_boolean((
const json_object*)item);
287#elif defined(WITH_CJSON)
288 return cJSON_IsFalse((
const cJSON*)item);
297#if defined(WITH_JSONC)
298 if (!json_object_is_type((
const json_object*)item, json_type_boolean))
300 json_bool val = json_object_get_boolean((
const json_object*)item);
302#elif defined(WITH_CJSON)
303 return cJSON_IsTrue((
const cJSON*)item);
312#if defined(WITH_JSONC)
313 return json_object_is_type((
const json_object*)item, json_type_boolean);
314#elif defined(WITH_CJSON)
315 return cJSON_IsBool((
const cJSON*)item);
324#if defined(WITH_JSONC)
325 return json_object_is_type((
const json_object*)item, json_type_null);
326#elif defined(WITH_CJSON)
327 return cJSON_IsNull((
const cJSON*)item);
336#if defined(WITH_JSONC)
337 return json_object_is_type((
const json_object*)item, json_type_int) ||
338 json_object_is_type((
const json_object*)item, json_type_double);
339#elif defined(WITH_CJSON)
340 return cJSON_IsNumber((
const cJSON*)item);
349#if defined(WITH_JSONC)
350 return json_object_is_type((
const json_object*)item, json_type_string);
351#elif defined(WITH_CJSON)
352 return cJSON_IsString((
const cJSON*)item);
361#if defined(WITH_JSONC)
362 return json_object_is_type((
const json_object*)item, json_type_array);
363#elif defined(WITH_CJSON)
364 return cJSON_IsArray((
const cJSON*)item);
373#if defined(WITH_JSONC)
374 return json_object_is_type((
const json_object*)item, json_type_object);
375#elif defined(WITH_CJSON)
376 return cJSON_IsObject((
const cJSON*)item);
385#if defined(WITH_JSONC)
386 return json_object_new_null();
387#elif defined(WITH_CJSON)
388 return cJSON_CreateNull();
396#if defined(WITH_JSONC)
397 return json_object_new_boolean(TRUE);
398#elif defined(WITH_CJSON)
399 return cJSON_CreateTrue();
407#if defined(WITH_JSONC)
408 return json_object_new_boolean(FALSE);
409#elif defined(WITH_CJSON)
410 return cJSON_CreateFalse();
418#if defined(WITH_JSONC)
419 return json_object_new_boolean(
boolean);
420#elif defined(WITH_CJSON)
421 return cJSON_CreateBool(
boolean);
423 WINPR_UNUSED(
boolean);
430#if defined(WITH_JSONC)
431 return json_object_new_double(num);
432#elif defined(WITH_CJSON)
433 return cJSON_CreateNumber(num);
442#if defined(WITH_JSONC)
443 return json_object_new_string(
string);
444#elif defined(WITH_CJSON)
445 return cJSON_CreateString(
string);
447 WINPR_UNUSED(
string);
454#if defined(WITH_JSONC)
455 return json_object_new_array();
456#elif defined(WITH_CJSON)
457 return cJSON_CreateArray();
465#if defined(WITH_JSONC)
466 return json_object_new_object();
467#elif defined(WITH_CJSON)
468 return cJSON_CreateObject();
476#if defined(WITH_JSONC)
477 struct json_object* obj = json_object_new_null();
478 if (json_object_object_add((json_object*)
object, name, obj) != 0)
480 json_object_put(obj);
484#elif defined(WITH_CJSON)
485 return cJSON_AddNullToObject((cJSON*)
object, name);
487 WINPR_UNUSED(
object);
495#if defined(WITH_JSONC)
496 struct json_object* obj = json_object_new_boolean(TRUE);
497 if (json_object_object_add((json_object*)
object, name, obj) != 0)
499 json_object_put(obj);
503#elif defined(WITH_CJSON)
504 return cJSON_AddTrueToObject((cJSON*)
object, name);
506 WINPR_UNUSED(
object);
514#if defined(WITH_JSONC)
515 struct json_object* obj = json_object_new_boolean(FALSE);
516 if (json_object_object_add((json_object*)
object, name, obj) != 0)
518 json_object_put(obj);
522#elif defined(WITH_CJSON)
523 return cJSON_AddFalseToObject((cJSON*)
object, name);
525 WINPR_UNUSED(
object);
533#if defined(WITH_JSONC)
534 struct json_object* obj = json_object_new_boolean(
boolean);
535 if (json_object_object_add((json_object*)
object, name, obj) != 0)
537 json_object_put(obj);
541#elif defined(WITH_CJSON)
542 return cJSON_AddBoolToObject((cJSON*)
object, name,
boolean);
544 WINPR_UNUSED(
object);
546 WINPR_UNUSED(
boolean);
553#if defined(WITH_JSONC)
554 struct json_object* obj = json_object_new_double(number);
555 if (json_object_object_add((json_object*)
object, name, obj) != 0)
557 json_object_put(obj);
561#elif defined(WITH_CJSON)
562 return cJSON_AddNumberToObject((cJSON*)
object, name, number);
564 WINPR_UNUSED(
object);
566 WINPR_UNUSED(number);
573#if defined(WITH_JSONC)
574 struct json_object* obj = json_object_new_string(
string);
575 if (json_object_object_add((json_object*)
object, name, obj) != 0)
577 json_object_put(obj);
581#elif defined(WITH_CJSON)
582 return cJSON_AddStringToObject((cJSON*)
object, name,
string);
584 WINPR_UNUSED(
object);
586 WINPR_UNUSED(
string);
593#if defined(WITH_JSONC)
594 struct json_object* obj = json_object_new_object();
595 if (json_object_object_add((json_object*)
object, name, obj) != 0)
597 json_object_put(obj);
601#elif defined(WITH_CJSON)
602 return cJSON_AddObjectToObject((cJSON*)
object, name);
604 WINPR_UNUSED(
object);
612#if defined(WITH_JSONC)
613 const int rc = json_object_array_add((json_object*)array, (json_object*)item);
617#elif defined(WITH_CJSON)
618#if defined(USE_CJSON_COMPAT)
619 if ((array == NULL) || (item == NULL))
621 cJSON_AddItemToArray((cJSON*)array, (cJSON*)item);
624 return cJSON_AddItemToArray((cJSON*)array, (cJSON*)item);
635#if defined(WITH_JSONC)
636 struct json_object* obj = json_object_new_array();
637 if (json_object_object_add((json_object*)
object, name, obj) != 0)
639 json_object_put(obj);
643#elif defined(WITH_CJSON)
644 return cJSON_AddArrayToObject((cJSON*)
object, name);
646 WINPR_UNUSED(
object);
654#if defined(WITH_JSONC)
655 const char* str = json_object_to_json_string_ext((json_object*)item, JSON_C_TO_STRING_PRETTY);
659#elif defined(WITH_CJSON)
660 return cJSON_Print((
const cJSON*)item);
669#if defined(WITH_JSONC)
670 const char* str = json_object_to_json_string_ext((json_object*)item, JSON_C_TO_STRING_PLAIN);
674#elif defined(WITH_CJSON)
675 return cJSON_PrintUnformatted((
const cJSON*)item);
WINPR_JSON * WINPR_JSON_CreateBool(BOOL boolean)
WINPR_JSON_CreateBool.
WINPR_JSON * WINPR_JSON_CreateString(const char *string)
WINPR_JSON_CreateString.
BOOL WINPR_JSON_HasObjectItem(const WINPR_JSON *object, const char *string)
Check if JSON has an object matching the name.
WINPR_JSON * WINPR_JSON_AddNumberToObject(WINPR_JSON *object, const char *name, double number)
WINPR_JSON_AddNumberToObject.
BOOL WINPR_JSON_IsNull(const WINPR_JSON *item)
Check if JSON item is Null.
WINPR_JSON * WINPR_JSON_GetObjectItem(const WINPR_JSON *object, const char *string)
Return a pointer to an JSON object item.
BOOL WINPR_JSON_IsString(const WINPR_JSON *item)
Check if JSON item is of type String.
BOOL WINPR_JSON_AddItemToArray(WINPR_JSON *array, WINPR_JSON *item)
Add an item to an existing array.
WINPR_JSON * WINPR_JSON_AddArrayToObject(WINPR_JSON *object, const char *name)
WINPR_JSON_AddArrayToObject.
BOOL WINPR_JSON_IsBool(const WINPR_JSON *item)
Check if JSON item is of type BOOL.
double WINPR_JSON_GetNumberValue(const WINPR_JSON *item)
Return the Number value of a JSON item.
WINPR_JSON * WINPR_JSON_AddTrueToObject(WINPR_JSON *object, const char *name)
WINPR_JSON_AddTrueToObject.
WINPR_JSON * WINPR_JSON_CreateObject(void)
WINPR_JSON_CreateObject.
WINPR_JSON * WINPR_JSON_CreateArray(void)
WINPR_JSON_CreateArray.
int WINPR_JSON_version(char *buffer, size_t len)
Get the library version string.
char * WINPR_JSON_Print(WINPR_JSON *item)
Serialize a JSON instance to string for minimal size without formatting see WINPR_JSON_PrintUnformatt...
WINPR_JSON * WINPR_JSON_AddFalseToObject(WINPR_JSON *object, const char *name)
WINPR_JSON_AddFalseToObject.
BOOL WINPR_JSON_IsNumber(const WINPR_JSON *item)
Check if JSON item is of type Number.
WINPR_JSON * WINPR_JSON_GetArrayItem(const WINPR_JSON *array, size_t index)
Return a pointer to an item in the array.
WINPR_JSON * WINPR_JSON_GetObjectItemCaseSensitive(const WINPR_JSON *object, const char *string)
Same as WINPR_JSON_GetObjectItem but with case insensitive matching.
WINPR_JSON * WINPR_JSON_AddStringToObject(WINPR_JSON *object, const char *name, const char *string)
WINPR_JSON_AddStringToObject.
WINPR_JSON * WINPR_JSON_ParseWithLength(const char *value, size_t buffer_length)
Parse a JSON string.
WINPR_JSON * WINPR_JSON_CreateFalse(void)
WINPR_JSON_CreateFalse.
WINPR_JSON * WINPR_JSON_CreateNumber(double num)
WINPR_JSON_CreateNumber.
BOOL WINPR_JSON_IsObject(const WINPR_JSON *item)
Check if JSON item is of type Object.
WINPR_JSON * WINPR_JSON_AddBoolToObject(WINPR_JSON *object, const char *name, BOOL boolean)
WINPR_JSON_AddBoolToObject.
BOOL WINPR_JSON_IsInvalid(const WINPR_JSON *item)
Check if JSON item is valid.
char * WINPR_JSON_PrintUnformatted(WINPR_JSON *item)
Serialize a JSON instance to string without formatting for human readable formatted output see WINPR_...
WINPR_JSON * WINPR_JSON_CreateNull(void)
WINPR_JSON_CreateNull.
const char * WINPR_JSON_GetStringValue(WINPR_JSON *item)
Return the String value of a JSON item.
WINPR_JSON * WINPR_JSON_AddNullToObject(WINPR_JSON *object, const char *name)
WINPR_JSON_AddNullToObject.
WINPR_JSON * WINPR_JSON_CreateTrue(void)
WINPR_JSON_CreateTrue.
BOOL WINPR_JSON_IsFalse(const WINPR_JSON *item)
Check if JSON item is BOOL value False.
void WINPR_JSON_Delete(WINPR_JSON *item)
Delete a WinPR JSON wrapper object.
size_t WINPR_JSON_GetArraySize(const WINPR_JSON *array)
Get the number of arrayitems from an array.
BOOL WINPR_JSON_IsArray(const WINPR_JSON *item)
Check if JSON item is of type Array.
const char * WINPR_JSON_GetErrorPtr(void)
Return an error string.
WINPR_JSON * WINPR_JSON_AddObjectToObject(WINPR_JSON *object, const char *name)
WINPR_JSON_AddObjectToObject.
WINPR_JSON * WINPR_JSON_Parse(const char *value)
Parse a '\0' terminated JSON string.
BOOL WINPR_JSON_IsTrue(const WINPR_JSON *item)
Check if JSON item is BOOL value True.