|  | @@ -12,6 +12,7 @@ Ultralightweight JSON parser in ANSI C.
 | 
	
		
			
				|  |  |    * [Working with the data structure](#working-with-the-data-structure)
 | 
	
		
			
				|  |  |    * [Parsing JSON](#parsing-json)
 | 
	
		
			
				|  |  |    * [Printing JSON](#printing-json)
 | 
	
		
			
				|  |  | +  * [Example](#example)
 | 
	
		
			
				|  |  |    * [Some JSON](#some-json)
 | 
	
		
			
				|  |  |    * [Here's the structure](#heres-the-structure)
 | 
	
		
			
				|  |  |    * [Caveats](#caveats)
 | 
	
	
		
			
				|  | @@ -252,6 +253,216 @@ If you have a rough idea of how big your resulting string will be, you can use `
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  These dynamic buffer allocations can be completely avoided by using `cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format)`. It takes a buffer to a pointer to print to and it's length. If the length is reached, printing will fail and it returns `0`. In case of success, `1` is returned. Note that you should provide 5 bytes more than is actually needed, because cJSON is not 100% accurate in estimating if the provided memory is enough.
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +### Example
 | 
	
		
			
				|  |  | +In this example we want to build and parse the following JSON:
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +```json
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +    "name": "Awesome 4K",
 | 
	
		
			
				|  |  | +    "resolutions": [
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            "width": 1280,
 | 
	
		
			
				|  |  | +            "height": 720
 | 
	
		
			
				|  |  | +        },
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            "width": 1920,
 | 
	
		
			
				|  |  | +            "height": 1080
 | 
	
		
			
				|  |  | +        },
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            "width": 3840,
 | 
	
		
			
				|  |  | +            "height": 2160
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    ]
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +```
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#### Printing
 | 
	
		
			
				|  |  | +Let's build the above JSON and print it to a string:
 | 
	
		
			
				|  |  | +```c
 | 
	
		
			
				|  |  | +//create a monitor with a list of supported resolutions
 | 
	
		
			
				|  |  | +char* create_monitor(void)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +    const unsigned int resolution_numbers[3][2] = {
 | 
	
		
			
				|  |  | +        {1280, 720},
 | 
	
		
			
				|  |  | +        {1920, 1080},
 | 
	
		
			
				|  |  | +        {3840, 2160}
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +    char *string = NULL;
 | 
	
		
			
				|  |  | +    cJSON *name = NULL;
 | 
	
		
			
				|  |  | +    cJSON *resolutions = NULL;
 | 
	
		
			
				|  |  | +    cJSON *resolution = NULL;
 | 
	
		
			
				|  |  | +    cJSON *width = NULL;
 | 
	
		
			
				|  |  | +    cJSON *height = NULL;
 | 
	
		
			
				|  |  | +    size_t index = 0;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    cJSON *monitor = cJSON_CreateObject();
 | 
	
		
			
				|  |  | +    if (monitor == NULL)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        goto end;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    name = cJSON_CreateString("Awesome 4K");
 | 
	
		
			
				|  |  | +    if (name == NULL)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        goto end;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    /* after creation was successful, immediately add it to the monitor,
 | 
	
		
			
				|  |  | +     * thereby transfering ownership of the pointer to it */
 | 
	
		
			
				|  |  | +    cJSON_AddItemToObject(monitor, "name", name);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    resolutions = cJSON_CreateArray();
 | 
	
		
			
				|  |  | +    if (resolutions == NULL)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        goto end;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    cJSON_AddItemToObject(monitor, "resolutions", resolutions);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    for (index = 0; index < (sizeof(resolution_numbers) / (2 * sizeof(int))); ++index)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        resolution = cJSON_CreateObject();
 | 
	
		
			
				|  |  | +        if (resolution == NULL)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            goto end;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        cJSON_AddItemToArray(resolutions, resolution);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        width = cJSON_CreateNumber(resolution_numbers[index][0]);
 | 
	
		
			
				|  |  | +        if (width == NULL)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            goto end;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        cJSON_AddItemToObject(resolution, "width", width);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        height = cJSON_CreateNumber(resolution_numbers[index][1]);
 | 
	
		
			
				|  |  | +        if (height == NULL)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            goto end;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        cJSON_AddItemToObject(resolution, "height", height);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    string = cJSON_Print(monitor);
 | 
	
		
			
				|  |  | +    if (string == NULL)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        fprintf(stderr, "Failed to print monitor.\n");
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +end:
 | 
	
		
			
				|  |  | +    cJSON_Delete(monitor);
 | 
	
		
			
				|  |  | +    return string;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +```
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +Alternatively we can use the `cJSON_Add...ToObject` helper functions to make our lifes a little easier:
 | 
	
		
			
				|  |  | +```c
 | 
	
		
			
				|  |  | +char *create_monitor_with_helpers(void)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +    const unsigned int resolution_numbers[3][2] = {
 | 
	
		
			
				|  |  | +        {1280, 720},
 | 
	
		
			
				|  |  | +        {1920, 1080},
 | 
	
		
			
				|  |  | +        {3840, 2160}
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +    char *string = NULL;
 | 
	
		
			
				|  |  | +    cJSON *resolutions = NULL;
 | 
	
		
			
				|  |  | +    size_t index = 0;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    cJSON *monitor = cJSON_CreateObject();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (cJSON_AddStringToObject(monitor, "name", "Awesome 4K") == NULL)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        goto end;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    resolutions = cJSON_AddArrayToObject(monitor, "resolutions");
 | 
	
		
			
				|  |  | +    if (resolutions == NULL)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        goto end;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    for (index = 0; index < (sizeof(resolution_numbers) / (2 * sizeof(int))); ++index)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        cJSON *resolution = cJSON_CreateObject();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        if (cJSON_AddNumberToObject(resolution, "width", resolution_numbers[index][0]) == NULL)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            goto end;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        if(cJSON_AddNumberToObject(resolution, "height", resolution_numbers[index][1]) == NULL)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            goto end;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        cJSON_AddItemToArray(resolutions, resolution);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    string = cJSON_Print(monitor);
 | 
	
		
			
				|  |  | +    if (string == NULL) {
 | 
	
		
			
				|  |  | +        fprintf(stderr, "Failed to print monitor.\n");
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +end:
 | 
	
		
			
				|  |  | +    cJSON_Delete(monitor);
 | 
	
		
			
				|  |  | +    return string;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +```
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#### Parsing
 | 
	
		
			
				|  |  | +In this example we will parse a JSON in the above format and check if the monitor supports a Full HD resolution while printing some diagnostic output:
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +```c
 | 
	
		
			
				|  |  | +/* return 1 if the monitor supports full hd, 0 otherwise */
 | 
	
		
			
				|  |  | +int supports_full_hd(const char * const monitor)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +    const cJSON *resolution = NULL;
 | 
	
		
			
				|  |  | +    const cJSON *resolutions = NULL;
 | 
	
		
			
				|  |  | +    const cJSON *name = NULL;
 | 
	
		
			
				|  |  | +    int status = 0;
 | 
	
		
			
				|  |  | +    cJSON *monitor_json = cJSON_Parse(monitor);
 | 
	
		
			
				|  |  | +    if (monitor_json == NULL)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        const char *error_ptr = cJSON_GetErrorPtr();
 | 
	
		
			
				|  |  | +        if (error_ptr != NULL)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            fprintf(stderr, "Error before: %s\n", error_ptr);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        status = 0;
 | 
	
		
			
				|  |  | +        goto end;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    name = cJSON_GetObjectItemCaseSensitive(monitor_json, "name");
 | 
	
		
			
				|  |  | +    if (cJSON_IsString(name) && (name->valuestring != NULL))
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        printf("Checking monitor \"%s\"\n", name->valuestring);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    resolutions = cJSON_GetObjectItemCaseSensitive(monitor_json, "resolutions");
 | 
	
		
			
				|  |  | +    cJSON_ArrayForEach(resolution, resolutions)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        cJSON *width = cJSON_GetObjectItemCaseSensitive(resolution, "width");
 | 
	
		
			
				|  |  | +        cJSON *height = cJSON_GetObjectItemCaseSensitive(resolution, "height");
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        if (!cJSON_IsNumber(width) || !cJSON_IsNumber(height))
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            status = 0;
 | 
	
		
			
				|  |  | +            goto end;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        if ((width->valuedouble == 1920) && (height->valuedouble == 1080))
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            status = 1;
 | 
	
		
			
				|  |  | +            goto end;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +end:
 | 
	
		
			
				|  |  | +    cJSON_Delete(monitor_json);
 | 
	
		
			
				|  |  | +    return status;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +```
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +Note that there are no NULL checks except for the result of `cJSON_Parse` because `cJSON_GetObjectItemCaseSensitive` checks for `NULL` inputs already, so a `NULL` value is just propagated and `cJSON_IsNumber` and `cJSON_IsString` return `0` if the input is `NULL`.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  ### Some JSON:
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  ```json
 |