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 (void)_snprintf(buffer, len,
"JSON support not available");
114#if defined(WITH_JSONC)
115 return json_tokener_parse(value);
116#elif defined(WITH_CJSON)
117 return cJSON_Parse(value);
126#if defined(WITH_JSONC)
127 WINPR_ASSERT(buffer_length <= INT_MAX);
128 json_tokener* tok = json_tokener_new();
131 json_object* obj = json_tokener_parse_ex(tok, value, (
int)buffer_length);
132 json_tokener_free(tok);
134#elif defined(WITH_CJSON)
135 return cJSON_ParseWithLength(value, buffer_length);
138 WINPR_UNUSED(buffer_length);
145#if defined(WITH_JSONC)
146 json_object_put((json_object*)item);
147#elif defined(WITH_CJSON)
148 cJSON_Delete((cJSON*)item);
156#if defined(WITH_JSONC)
157 return json_object_array_get_idx((
const json_object*)array, index);
158#elif defined(WITH_CJSON)
159 WINPR_ASSERT(index <= INT_MAX);
160 return cJSON_GetArrayItem((
const cJSON*)array, (INT)index);
170#if defined(WITH_JSONC)
171 return json_object_array_length((
const json_object*)array);
172#elif defined(WITH_CJSON)
173 const int rc = cJSON_GetArraySize((
const cJSON*)array);
185#if defined(WITH_JSONC)
186 return json_object_object_get((
const json_object*)
object,
string);
187#elif defined(WITH_CJSON)
188 return cJSON_GetObjectItem((
const cJSON*)
object,
string);
190 WINPR_UNUSED(
object);
191 WINPR_UNUSED(
string);
198#if defined(WITH_JSONC)
199 return json_object_object_get((
const json_object*)
object,
string);
200#elif defined(WITH_CJSON)
201 return cJSON_GetObjectItemCaseSensitive((
const cJSON*)
object,
string);
203 WINPR_UNUSED(
object);
204 WINPR_UNUSED(
string);
211#if defined(WITH_JSONC)
212 return json_object_object_get_ex((
const json_object*)
object,
string, NULL);
213#elif defined(WITH_CJSON)
214 return cJSON_HasObjectItem((
const cJSON*)
object,
string);
216 WINPR_UNUSED(
object);
217 WINPR_UNUSED(
string);
224#if defined(WITH_JSONC)
225 return json_util_get_last_err();
226#elif defined(WITH_CJSON)
227 return cJSON_GetErrorPtr();
235#if defined(WITH_JSONC)
236 return json_object_get_string((json_object*)item);
237#elif defined(WITH_CJSON)
238 return cJSON_GetStringValue((cJSON*)item);
247#if defined(WITH_JSONC)
248 return json_object_get_double((
const json_object*)item);
249#elif defined(WITH_CJSON)
250 return cJSON_GetNumberValue((
const cJSON*)item);
259#if defined(WITH_JSONC)
273#elif defined(WITH_CJSON)
274 return cJSON_IsInvalid((
const cJSON*)item);
283#if defined(WITH_JSONC)
284 if (!json_object_is_type((
const json_object*)item, json_type_boolean))
286 json_bool val = json_object_get_boolean((
const json_object*)item);
288#elif defined(WITH_CJSON)
289 return cJSON_IsFalse((
const cJSON*)item);
298#if defined(WITH_JSONC)
299 if (!json_object_is_type((
const json_object*)item, json_type_boolean))
301 json_bool val = json_object_get_boolean((
const json_object*)item);
303#elif defined(WITH_CJSON)
304 return cJSON_IsTrue((
const cJSON*)item);
313#if defined(WITH_JSONC)
314 return json_object_is_type((
const json_object*)item, json_type_boolean);
315#elif defined(WITH_CJSON)
316 return cJSON_IsBool((
const cJSON*)item);
325#if defined(WITH_JSONC)
326 return json_object_is_type((
const json_object*)item, json_type_null);
327#elif defined(WITH_CJSON)
328 return cJSON_IsNull((
const cJSON*)item);
337#if defined(WITH_JSONC)
338 return json_object_is_type((
const json_object*)item, json_type_int) ||
339 json_object_is_type((
const json_object*)item, json_type_double);
340#elif defined(WITH_CJSON)
341 return cJSON_IsNumber((
const cJSON*)item);
350#if defined(WITH_JSONC)
351 return json_object_is_type((
const json_object*)item, json_type_string);
352#elif defined(WITH_CJSON)
353 return cJSON_IsString((
const cJSON*)item);
362#if defined(WITH_JSONC)
363 return json_object_is_type((
const json_object*)item, json_type_array);
364#elif defined(WITH_CJSON)
365 return cJSON_IsArray((
const cJSON*)item);
374#if defined(WITH_JSONC)
375 return json_object_is_type((
const json_object*)item, json_type_object);
376#elif defined(WITH_CJSON)
377 return cJSON_IsObject((
const cJSON*)item);
386#if defined(WITH_JSONC)
387 return json_object_new_null();
388#elif defined(WITH_CJSON)
389 return cJSON_CreateNull();
397#if defined(WITH_JSONC)
398 return json_object_new_boolean(TRUE);
399#elif defined(WITH_CJSON)
400 return cJSON_CreateTrue();
408#if defined(WITH_JSONC)
409 return json_object_new_boolean(FALSE);
410#elif defined(WITH_CJSON)
411 return cJSON_CreateFalse();
419#if defined(WITH_JSONC)
420 return json_object_new_boolean(
boolean);
421#elif defined(WITH_CJSON)
422 return cJSON_CreateBool(
boolean);
424 WINPR_UNUSED(
boolean);
431#if defined(WITH_JSONC)
432 return json_object_new_double(num);
433#elif defined(WITH_CJSON)
434 return cJSON_CreateNumber(num);
443#if defined(WITH_JSONC)
444 return json_object_new_string(
string);
445#elif defined(WITH_CJSON)
446 return cJSON_CreateString(
string);
448 WINPR_UNUSED(
string);
455#if defined(WITH_JSONC)
456 return json_object_new_array();
457#elif defined(WITH_CJSON)
458 return cJSON_CreateArray();
466#if defined(WITH_JSONC)
467 return json_object_new_object();
468#elif defined(WITH_CJSON)
469 return cJSON_CreateObject();
477#if defined(WITH_JSONC)
478 struct json_object* obj = json_object_new_null();
479 if (json_object_object_add((json_object*)
object, name, obj) != 0)
481 json_object_put(obj);
485#elif defined(WITH_CJSON)
486 return cJSON_AddNullToObject((cJSON*)
object, name);
488 WINPR_UNUSED(
object);
496#if defined(WITH_JSONC)
497 struct json_object* obj = json_object_new_boolean(TRUE);
498 if (json_object_object_add((json_object*)
object, name, obj) != 0)
500 json_object_put(obj);
504#elif defined(WITH_CJSON)
505 return cJSON_AddTrueToObject((cJSON*)
object, name);
507 WINPR_UNUSED(
object);
515#if defined(WITH_JSONC)
516 struct json_object* obj = json_object_new_boolean(FALSE);
517 if (json_object_object_add((json_object*)
object, name, obj) != 0)
519 json_object_put(obj);
523#elif defined(WITH_CJSON)
524 return cJSON_AddFalseToObject((cJSON*)
object, name);
526 WINPR_UNUSED(
object);
534#if defined(WITH_JSONC)
535 struct json_object* obj = json_object_new_boolean(
boolean);
536 if (json_object_object_add((json_object*)
object, name, obj) != 0)
538 json_object_put(obj);
542#elif defined(WITH_CJSON)
543 return cJSON_AddBoolToObject((cJSON*)
object, name,
boolean);
545 WINPR_UNUSED(
object);
547 WINPR_UNUSED(
boolean);
554#if defined(WITH_JSONC)
555 struct json_object* obj = json_object_new_double(number);
556 if (json_object_object_add((json_object*)
object, name, obj) != 0)
558 json_object_put(obj);
562#elif defined(WITH_CJSON)
563 return cJSON_AddNumberToObject((cJSON*)
object, name, number);
565 WINPR_UNUSED(
object);
567 WINPR_UNUSED(number);
574#if defined(WITH_JSONC)
575 struct json_object* obj = json_object_new_string(
string);
576 if (json_object_object_add((json_object*)
object, name, obj) != 0)
578 json_object_put(obj);
582#elif defined(WITH_CJSON)
583 return cJSON_AddStringToObject((cJSON*)
object, name,
string);
585 WINPR_UNUSED(
object);
587 WINPR_UNUSED(
string);
594#if defined(WITH_JSONC)
595 struct json_object* obj = json_object_new_object();
596 if (json_object_object_add((json_object*)
object, name, obj) != 0)
598 json_object_put(obj);
602#elif defined(WITH_CJSON)
603 return cJSON_AddObjectToObject((cJSON*)
object, name);
605 WINPR_UNUSED(
object);
613#if defined(WITH_JSONC)
614 const int rc = json_object_array_add((json_object*)array, (json_object*)item);
618#elif defined(WITH_CJSON)
619#if defined(USE_CJSON_COMPAT)
620 if ((array == NULL) || (item == NULL))
622 cJSON_AddItemToArray((cJSON*)array, (cJSON*)item);
625 return cJSON_AddItemToArray((cJSON*)array, (cJSON*)item);
636#if defined(WITH_JSONC)
637 struct json_object* obj = json_object_new_array();
638 if (json_object_object_add((json_object*)
object, name, obj) != 0)
640 json_object_put(obj);
644#elif defined(WITH_CJSON)
645 return cJSON_AddArrayToObject((cJSON*)
object, name);
647 WINPR_UNUSED(
object);
655#if defined(WITH_JSONC)
656 const char* str = json_object_to_json_string_ext((json_object*)item, JSON_C_TO_STRING_PRETTY);
660#elif defined(WITH_CJSON)
661 return cJSON_Print((
const cJSON*)item);
670#if defined(WITH_JSONC)
671 const char* str = json_object_to_json_string_ext((json_object*)item, JSON_C_TO_STRING_PLAIN);
675#elif defined(WITH_CJSON)
676 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.