Ultralightweight JSON parser in ANSI C

Related tags

JSON cJSON
Overview

cJSON

Ultralightweight JSON parser in ANSI C.

Table of contents

License

MIT License

Copyright (c) 2009-2017 Dave Gamble and cJSON contributors

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Usage

Welcome to cJSON.

cJSON aims to be the dumbest possible parser that you can get your job done with. It's a single file of C, and a single header file.

JSON is described best here: http://www.json.org/ It's like XML, but fat-free. You use it to move data around, store things, or just generally represent your program's state.

As a library, cJSON exists to take away as much legwork as it can, but not get in your way. As a point of pragmatism (i.e. ignoring the truth), I'm going to say that you can use it in one of two modes: Auto and Manual. Let's have a quick run-through.

I lifted some JSON from this page: http://www.json.org/fatfree.html That page inspired me to write cJSON, which is a parser that tries to share the same philosophy as JSON itself. Simple, dumb, out of the way.

Building

There are several ways to incorporate cJSON into your project.

copying the source

Because the entire library is only one C file and one header file, you can just copy cJSON.h and cJSON.c to your projects source and start using it.

cJSON is written in ANSI C (C89) in order to support as many platforms and compilers as possible.

CMake

With CMake, cJSON supports a full blown build system. This way you get the most features. CMake with an equal or higher version than 2.8.5 is supported. With CMake it is recommended to do an out of tree build, meaning the compiled files are put in a directory separate from the source files. So in order to build cJSON with CMake on a Unix platform, make a build directory and run CMake inside it.

mkdir build
cd build
cmake ..

This will create a Makefile and a bunch of other files. You can then compile it:

make

And install it with make install if you want. By default it installs the headers /usr/local/include/cjson and the libraries to /usr/local/lib. It also installs files for pkg-config to make it easier to detect and use an existing installation of CMake. And it installs CMake config files, that can be used by other CMake based projects to discover the library.

You can change the build process with a list of different options that you can pass to CMake. Turn them on with On and off with Off:

  • -DENABLE_CJSON_TEST=On: Enable building the tests. (on by default)
  • -DENABLE_CJSON_UTILS=On: Enable building cJSON_Utils. (off by default)
  • -DENABLE_TARGET_EXPORT=On: Enable the export of CMake targets. Turn off if it makes problems. (on by default)
  • -DENABLE_CUSTOM_COMPILER_FLAGS=On: Enable custom compiler flags (currently for Clang, GCC and MSVC). Turn off if it makes problems. (on by default)
  • -DENABLE_VALGRIND=On: Run tests with valgrind. (off by default)
  • -DENABLE_SANITIZERS=On: Compile cJSON with AddressSanitizer and UndefinedBehaviorSanitizer enabled (if possible). (off by default)
  • -DENABLE_SAFE_STACK: Enable the SafeStack instrumentation pass. Currently only works with the Clang compiler. (off by default)
  • -DBUILD_SHARED_LIBS=On: Build the shared libraries. (on by default)
  • -DBUILD_SHARED_AND_STATIC_LIBS=On: Build both shared and static libraries. (off by default)
  • -DCMAKE_INSTALL_PREFIX=/usr: Set a prefix for the installation.
  • -DENABLE_LOCALES=On: Enable the usage of localeconv method. ( on by default )
  • -DCJSON_OVERRIDE_BUILD_SHARED_LIBS=On: Enable overriding the value of BUILD_SHARED_LIBS with -DCJSON_BUILD_SHARED_LIBS.

If you are packaging cJSON for a distribution of Linux, you would probably take these steps for example:

mkdir build
cd build
cmake .. -DENABLE_CJSON_UTILS=On -DENABLE_CJSON_TEST=Off -DCMAKE_INSTALL_PREFIX=/usr
make
make DESTDIR=$pkgdir install

On Windows CMake is usually used to create a Visual Studio solution file by running it inside the Developer Command Prompt for Visual Studio, for exact steps follow the official documentation from CMake and Microsoft and use the online search engine of your choice. The descriptions of the the options above still generally apply, although not all of them work on Windows.

Makefile

NOTE: This Method is deprecated. Use CMake if at all possible. Makefile support is limited to fixing bugs.

If you don't have CMake available, but still have GNU make. You can use the makefile to build cJSON:

Run this command in the directory with the source code and it will automatically compile static and shared libraries and a little test program (not the full test suite).

make all

If you want, you can install the compiled library to your system using make install. By default it will install the headers in /usr/local/include/cjson and the libraries in /usr/local/lib. But you can change this behavior by setting the PREFIX and DESTDIR variables: make PREFIX=/usr DESTDIR=temp install. And uninstall them with: make PREFIX=/usr DESTDIR=temp uninstall.

Vcpkg

You can download and install cJSON using the vcpkg dependency manager:

git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg integrate install
vcpkg install cjson

The cJSON port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please create an issue or pull request on the vcpkg repository.

Including cJSON

If you installed it via CMake or the Makefile, you can include cJSON like this:

#include <cjson/cJSON.h>

Data Structure

cJSON represents JSON data using the cJSON struct data type:

/* The cJSON structure: */
typedef struct cJSON
{
    struct cJSON *next;
    struct cJSON *prev;
    struct cJSON *child;
    int type;
    char *valuestring;
    /* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
    int valueint;
    double valuedouble;
    char *string;
} cJSON;

An item of this type represents a JSON value. The type is stored in type as a bit-flag (this means that you cannot find out the type by just comparing the value of type).

To check the type of an item, use the corresponding cJSON_Is... function. It does a NULL check followed by a type check and returns a boolean value if the item is of this type.

The type can be one of the following:

  • cJSON_Invalid (check with cJSON_IsInvalid): Represents an invalid item that doesn't contain any value. You automatically have this type if you set the item to all zero bytes.
  • cJSON_False (check with cJSON_IsFalse): Represents a false boolean value. You can also check for boolean values in general with cJSON_IsBool.
  • cJSON_True (check with cJSON_IsTrue): Represents a true boolean value. You can also check for boolean values in general with cJSON_IsBool.
  • cJSON_NULL (check with cJSON_IsNull): Represents a null value.
  • cJSON_Number (check with cJSON_IsNumber): Represents a number value. The value is stored as a double in valuedouble and also in valueint. If the number is outside of the range of an integer, INT_MAX or INT_MIN are used for valueint.
  • cJSON_String (check with cJSON_IsString): Represents a string value. It is stored in the form of a zero terminated string in valuestring.
  • cJSON_Array (check with cJSON_IsArray): Represent an array value. This is implemented by pointing child to a linked list of cJSON items that represent the values in the array. The elements are linked together using next and prev, where the first element has prev.next == NULL and the last element next == NULL.
  • cJSON_Object (check with cJSON_IsObject): Represents an object value. Objects are stored same way as an array, the only difference is that the items in the object store their keys in string.
  • cJSON_Raw (check with cJSON_IsRaw): Represents any kind of JSON that is stored as a zero terminated array of characters in valuestring. This can be used, for example, to avoid printing the same static JSON over and over again to save performance. cJSON will never create this type when parsing. Also note that cJSON doesn't check if it is valid JSON.

Additionally there are the following two flags:

  • cJSON_IsReference: Specifies that the item that child points to and/or valuestring is not owned by this item, it is only a reference. So cJSON_Delete and other functions will only deallocate this item, not its child/valuestring.
  • cJSON_StringIsConst: This means that string points to a constant string. This means that cJSON_Delete and other functions will not try to deallocate string.

Working with the data structure

For every value type there is a cJSON_Create... function that can be used to create an item of that type. All of these will allocate a cJSON struct that can later be deleted with cJSON_Delete. Note that you have to delete them at some point, otherwise you will get a memory leak.
Important: If you have added an item to an array or an object already, you mustn't delete it with cJSON_Delete. Adding it to an array or object transfers its ownership so that when that array or object is deleted, it gets deleted as well. You also could use cJSON_SetValuestring to change a cJSON_String's valuestring, and you needn't to free the previous valuestring manually.

Basic types

  • null is created with cJSON_CreateNull
  • booleans are created with cJSON_CreateTrue, cJSON_CreateFalse or cJSON_CreateBool
  • numbers are created with cJSON_CreateNumber. This will set both valuedouble and valueint. If the number is outside of the range of an integer, INT_MAX or INT_MIN are used for valueint
  • strings are created with cJSON_CreateString (copies the string) or with cJSON_CreateStringReference (directly points to the string. This means that valuestring won't be deleted by cJSON_Delete and you are responsible for its lifetime, useful for constants)

Arrays

You can create an empty array with cJSON_CreateArray. cJSON_CreateArrayReference can be used to create an array that doesn't "own" its content, so its content doesn't get deleted by cJSON_Delete.

To add items to an array, use cJSON_AddItemToArray to append items to the end. Using cJSON_AddItemReferenceToArray an element can be added as a reference to another item, array or string. This means that cJSON_Delete will not delete that items child or valuestring properties, so no double frees are occurring if they are already used elsewhere. To insert items in the middle, use cJSON_InsertItemInArray. It will insert an item at the given 0 based index and shift all the existing items to the right.

If you want to take an item out of an array at a given index and continue using it, use cJSON_DetachItemFromArray, it will return the detached item, so be sure to assign it to a pointer, otherwise you will have a memory leak.

Deleting items is done with cJSON_DeleteItemFromArray. It works like cJSON_DetachItemFromArray, but deletes the detached item via cJSON_Delete.

You can also replace an item in an array in place. Either with cJSON_ReplaceItemInArray using an index or with cJSON_ReplaceItemViaPointer given a pointer to an element. cJSON_ReplaceItemViaPointer will return 0 if it fails. What this does internally is to detach the old item, delete it and insert the new item in its place.

To get the size of an array, use cJSON_GetArraySize. Use cJSON_GetArrayItem to get an element at a given index.

Because an array is stored as a linked list, iterating it via index is inefficient (O(n²)), so you can iterate over an array using the cJSON_ArrayForEach macro in O(n) time complexity.

Objects

You can create an empty object with cJSON_CreateObject. cJSON_CreateObjectReference can be used to create an object that doesn't "own" its content, so its content doesn't get deleted by cJSON_Delete.

To add items to an object, use cJSON_AddItemToObject. Use cJSON_AddItemToObjectCS to add an item to an object with a name that is a constant or reference (key of the item, string in the cJSON struct), so that it doesn't get freed by cJSON_Delete. Using cJSON_AddItemReferenceToArray an element can be added as a reference to another object, array or string. This means that cJSON_Delete will not delete that items child or valuestring properties, so no double frees are occurring if they are already used elsewhere.

If you want to take an item out of an object, use cJSON_DetachItemFromObjectCaseSensitive, it will return the detached item, so be sure to assign it to a pointer, otherwise you will have a memory leak.

Deleting items is done with cJSON_DeleteItemFromObjectCaseSensitive. It works like cJSON_DetachItemFromObjectCaseSensitive followed by cJSON_Delete.

You can also replace an item in an object in place. Either with cJSON_ReplaceItemInObjectCaseSensitive using a key or with cJSON_ReplaceItemViaPointer given a pointer to an element. cJSON_ReplaceItemViaPointer will return 0 if it fails. What this does internally is to detach the old item, delete it and insert the new item in its place.

To get the size of an object, you can use cJSON_GetArraySize, this works because internally objects are stored as arrays.

If you want to access an item in an object, use cJSON_GetObjectItemCaseSensitive.

To iterate over an object, you can use the cJSON_ArrayForEach macro the same way as for arrays.

cJSON also provides convenient helper functions for quickly creating a new item and adding it to an object, like cJSON_AddNullToObject. They return a pointer to the new item or NULL if they failed.

Parsing JSON

Given some JSON in a zero terminated string, you can parse it with cJSON_Parse.

cJSON *json = cJSON_Parse(string);

Given some JSON in a string (whether zero terminated or not), you can parse it with cJSON_ParseWithLength.

cJSON *json = cJSON_ParseWithLength(string, buffer_length);

It will parse the JSON and allocate a tree of cJSON items that represents it. Once it returns, you are fully responsible for deallocating it after use with cJSON_Delete.

The allocator used by cJSON_Parse is malloc and free by default but can be changed (globally) with cJSON_InitHooks.

If an error occurs a pointer to the position of the error in the input string can be accessed using cJSON_GetErrorPtr. Note though that this can produce race conditions in multithreading scenarios, in that case it is better to use cJSON_ParseWithOpts with return_parse_end. By default, characters in the input string that follow the parsed JSON will not be considered as an error.

If you want more options, use cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated). return_parse_end returns a pointer to the end of the JSON in the input string or the position that an error occurs at (thereby replacing cJSON_GetErrorPtr in a thread safe way). require_null_terminated, if set to 1 will make it an error if the input string contains data after the JSON.

If you want more options giving buffer length, use cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated).

Printing JSON

Given a tree of cJSON items, you can print them as a string using cJSON_Print.

char *string = cJSON_Print(json);

It will allocate a string and print a JSON representation of the tree into it. Once it returns, you are fully responsible for deallocating it after use with your allocator. (usually free, depends on what has been set with cJSON_InitHooks).

cJSON_Print will print with whitespace for formatting. If you want to print without formatting, use cJSON_PrintUnformatted.

If you have a rough idea of how big your resulting string will be, you can use cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt). fmt is a boolean to turn formatting with whitespace on and off. prebuffer specifies the first buffer size to use for printing. cJSON_Print currently uses 256 bytes for its first buffer size. Once printing runs out of space, a new buffer is allocated and the old gets copied over before printing is continued.

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 its 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:

{
    "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:

//create a monitor with a list of supported resolutions
//NOTE: Returns a heap allocated string, you are required to free it after use.
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 transferring 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:

//NOTE: Returns a heap allocated string, you are required to free it after use.
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:

/* 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.

Caveats

Zero Character

cJSON doesn't support strings that contain the zero character '\0' or \u0000. This is impossible with the current API because strings are zero terminated.

Character Encoding

cJSON only supports UTF-8 encoded input. In most cases it doesn't reject invalid UTF-8 as input though, it just propagates it through as is. As long as the input doesn't contain invalid UTF-8, the output will always be valid UTF-8.

C Standard

cJSON is written in ANSI C (or C89, C90). If your compiler or C library doesn't follow this standard, correct behavior is not guaranteed.

NOTE: ANSI C is not C++ therefore it shouldn't be compiled with a C++ compiler. You can compile it with a C compiler and link it with your C++ code however. Although compiling with a C++ compiler might work, correct behavior is not guaranteed.

Floating Point Numbers

cJSON does not officially support any double implementations other than IEEE754 double precision floating point numbers. It might still work with other implementations but bugs with these will be considered invalid.

The maximum length of a floating point literal that cJSON supports is currently 63 characters.

Deep Nesting Of Arrays And Objects

cJSON doesn't support arrays and objects that are nested too deeply because this would result in a stack overflow. To prevent this cJSON limits the depth to CJSON_NESTING_LIMIT which is 1000 by default but can be changed at compile time.

Thread Safety

In general cJSON is not thread safe.

However it is thread safe under the following conditions:

  • cJSON_GetErrorPtr is never used (the return_parse_end parameter of cJSON_ParseWithOpts can be used instead)
  • cJSON_InitHooks is only ever called before using cJSON in any threads.
  • setlocale is never called before all calls to cJSON functions have returned.

Case Sensitivity

When cJSON was originally created, it didn't follow the JSON standard and didn't make a distinction between uppercase and lowercase letters. If you want the correct, standard compliant, behavior, you need to use the CaseSensitive functions where available.

Duplicate Object Members

cJSON supports parsing and printing JSON that contains objects that have multiple members with the same name. cJSON_GetObjectItemCaseSensitive however will always only return the first one.

Enjoy cJSON!

  • Dave Gamble (original author)
  • Max Bruckner and Alan Wang (current maintainer)
  • and the other cJSON contributors
Issues
  • Make source code readable

    Make source code readable

    Let's face it, cJSON's source code is looking quite horrible in the current form. The way it is it's bad for potential contributors because it is hard to read and it also makes tracking changes with git harder.

    I would volunteer to reformat the code if you let me. I will follow the format you like, but here's a suggestion:

    Currently:

    /* Parse the input text to generate a number, and populate the result into item. */
    static const char *parse_number(cJSON *item,const char *num)
    {
        double n=0,sign=1,scale=0;int subscale=0,signsubscale=1;
    
        if (*num=='-') sign=-1,num++;   /* Has sign? */
        if (*num=='0') num++;           /* is zero */
        if (*num>='1' && *num<='9') do  n=(n*10.0)+(*num++ -'0');   while (*num>='0' && *num<='9'); /* Number? */
        if (*num=='.' && num[1]>='0' && num[1]<='9') {num++;        do  n=(n*10.0)+(*num++ -'0'),scale--; while (*num>='0' && *num<='9');}  /* Fractional part? */
        if (*num=='e' || *num=='E')     /* Exponent? */
        {   num++;if (*num=='+') num++; else if (*num=='-') signsubscale=-1,num++;      /* With sign? */
            while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0');   /* Number? */
        }
    
        n=sign*n*pow(10.0,(scale+subscale*signsubscale));   /* number = +/- number.fraction * 10^+/- exponent */
    
        item->valuedouble=n;
        item->valueint=(int)n;
        item->type=cJSON_Number;
        return num;
    }
    

    After reformatting:

    /* Parse the input text to generate a number, and populate the result into item. */
    static const char *parse_number(cJSON *item,const char *num) {
        double n = 0;
        double sign = 1;
        double scale = 0;
        int subscale = 0;
        int signsubscale = 1;
    
        /* Has sign? */
        if (*num == '-') {
            sign = -1;
            num++;
        }
    
        /* is zero */
        if (*num == '0') {
            num++;
        }
        if ((*num >= '1') && (*num <= '9')) {
            do {
                n = (n * 10.0) + (*num++ - '0');
            } while ((*num >= '0') && (*num <= '9')); /* Number? */
        }
        /* Fractional part? */
        if ((*num == '.') && (num[1] >= '0') && (num[1] <= '9')) {
            num++;
            do {
                n = (n * 10.0) + (*num++ - '0');
                scale--;
            } while ((*num >= '0') && (*num <= '9'));
        }
        /* Exponent? */
        if ((*num == 'e') || (*num == 'E')) {
            num++;
            /* With sign? */
            if (*num == '+') {
                num++;
            } else if (*num == '-') {
                signsubscale = -1;
                num++;
            }
            while ((*num >= '0') && (*num <= '9')) {/* Number? */
                subscale = (subscale * 10) + (*num++ - '0');
            }
        }
    
        /* number = +/- number.fraction * 10^+/- exponent */
        n = sign * n * pow(10.0, (scale + subscale * signsubscale));
    
        item->valuedouble = n;
        item->valueint = (int) n;
        item->type = cJSON_Number;
        return num;
    }
    
    enhancement 
    opened by FSMaxB 39
  • Make cJSON const correct.

    Make cJSON const correct.

    Const correctness is embedded software is a big deal. Typically strings are really stored in flash, so it is just not possible to change them.

    There was a long-running discussion how to deal with const correctness in pull request #80. It was decided for v1 to cJSON to temporarily disable casting away const.

    For v2 of cJSON I'd like to clean up this issue completely.

    I really appreciate the effort to have the possibility of using string literals for JSON names by introducing cJSON_AddItemToObjectCS(). Nevertheless, a better name for that function would be cJSON_AddItemToObjectByRef() because that indicates more clearly that cJSON has not taken the ownership of that name (so cJSON will not free it). For consistency reasons I would also rename the flag string_is_const to name_is_ref.

    We would now have two sources of names:

    1. Coming in by reference
    2. Copied by cJSON via strdup(). These names are subject tofree().

    To deal with both situations correctly, I propose to introduce a union for name:

    union {
        const char *ref_name;
        char *name;
    } name;
    

    Using the flag name_is_ref we can access the correct union member inside the library correctly. To free users of the library to fiddly around with that union, we should introduce an access function like const * cJSON_GetName(const cJSON *object). This function will return the correct pointer with respect to name_is_ref. It should be noted that the return value of that function is const, so writes to names (even to the union member char *name) is not forbidden by the compiler. I think this is a very minor restriction, I can't construct good use cases where users want to write to that name.

    BTW, we can do exactly the same for value->string by introducing value->const_string and an additional flag value_string_is_ref. This would make the whole library const correct and will sometimes save a lot of memory allocations/deallocations, especially when creating lots of cJSON objects from string literals.

    Comments are very welcome.

    opened by gatzka 18
  • Alternative to Malloc for embedded device

    Alternative to Malloc for embedded device

    Hi, Thanks for the useful library, it is great! I have faced one problem with embedded device (NEW8110 EFT POS to be explicit) whereby using malloc() ends up with Data abort exception that have some code I cannot understand. Now since I want to use CJSON in this device, is there a way out? Can I use CJSON without invoking malloc at all?

    Google plus searching issues here have not helped. The SDK documentation mentions nothing and the support have expired which means am on my own!

    Device: NEW8110 EFT POS, ARM9 Compiler: arm-linux-uclib-gcc 4.1.2

    Let me know if any more information is needed

    TIA, Stefano

    question 
    opened by mtangoo 16
  • static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer)

    static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer)

    The print_value() very absurd!!! eg: (1) if output_buffer->buffer is global, the function is very danger!!! (2) struct{ int flag; char buf[]; } if output_buffer->buffer point to buf[] and buf[] realloced, oh mg god!!!

    opened by mengxiangren 15
  • if end pointer non null, assumes end of string

    if end pointer non null, assumes end of string

    Hello,

    This modifies parse with opts so that if the return end pointer is pointing than that is the end of the string so as to not use strlen. Was not sure of other method to parse something that is not a string. I added small test case.

    Could not find a method to parse "memory" as opposed to parse string.

    opened by TomzBench 15
  • RFC: Make string in struct cJSON const.

    RFC: Make string in struct cJSON const.

    Const correctness is embedded software is a big deal. Typically strings are really stored in flash, so it is just not possible to change them.

    The cast item->string = (char)string in cJSON_AddItemToObjectCS allows a programmer to write to item>string later on without a compiler warning. That's the reason why it makes sense to make the string member const.

    The code really has no problems when doing so besides the nasty fact that free() does not allow to pass const pointers. Therefore the ugly pragma statements. Nevertheless, I'm always in favor to make the API clean and to handle the somehow incompatible parts inside the library.

    I'm eager to hear comments.

    opened by gatzka 15
  • Created REVIEW

    Created REVIEW

    http://warmachine.rf.gd/2017/04/01/cjson-review/ is my tiny effort to bring light to the ones who are just starting out with network programming, and want to use some kind of simple data-exchange format for their program.

    opened by hatlesshacker 13
  • Need public API to free returned strings (e.g. cJSON_Print)

    Need public API to free returned strings (e.g. cJSON_Print)

    There should be a public API to free returned strings like from cJSON_Print().

    My usage case is that I'm writing a middleware library that uses cJSON. The user is free to use cJSON elsewhere in their project. I don't necessarily know what memory allocator they are using, so when I call cJSON_Print(), I don't know what free() function to call. cJSON_free is private/internal.

    I'm thinking either adding a cJSON_FreeString() which wraps cJSON_free, or making CJSON_free public are the easiest solutions.

    Thank you

    opened by ewmailing 13
  • cjson_utils patch does not work (memory issue) on patches defined in http://jsonpatch.com/

    cjson_utils patch does not work (memory issue) on patches defined in http://jsonpatch.com/

    Hi,

    I tried the patch example given in http://jsonpatch.com/#simple-example. The patch which removes a path causes the bug. The generated patch by the library is different.

    My main.c file is

    #include <stdio.h>
    #include <stdlib.h>     /* malloc, calloc, realloc, free */
    #include <cJSON_Utils.h>
    
    int main()
    {
        /* see: http://jsonpatch.com/ */
        char * objectJSONString = "{\"baz\":\"qux\",\"foo\":\"bar\"}";
        char * objectJSONPatchesString = "[\
        { \"op\": \"replace\", \"path\": \"/baz\", \"value\": \"boo\" },\
        { \"op\": \"add\", \"path\": \"/hello\", \"value\": [\"world\"] },\
        { \"op\": \"remove\", \"path\": \"/foo\" }\
      ]";
        char * expectedPatchedObjectString = "{\"baz\": \"boo\",\"hello\": [\"world\"]}";
        char * freeme = NULL;
        cJSON_InitHooks(NULL);
    
        /* object to patch */
        cJSON * objectJSON = cJSON_Parse(objectJSONString);
        if (objectJSON != NULL) {
            freeme = cJSON_Print(objectJSON);
            printf("Created object parsed from string:\n%s\n", cJSON_Print(objectJSON));
            cJSON_free(freeme);
        }
    
        /* patches to apply */
        cJSON * patchesJSON = cJSON_Parse(objectJSONPatchesString);
        if (patchesJSON != NULL) {
            freeme = cJSON_Print(patchesJSON);
            printf("Created patches parsed from string:\n%s\n", cJSON_Print(patchesJSON));
            cJSON_free(freeme);
        }
    
        /* Expected object to get after applying the patch */
        cJSON * expectedPatchedJSON = cJSON_Parse(expectedPatchedObjectString);
        if (expectedPatchedJSON != NULL) {
            freeme = cJSON_Print(expectedPatchedJSON);
            printf("Expected patched object parsed from string:\n%s\n", cJSON_Print(expectedPatchedJSON));
            cJSON_free(freeme);
        }
    
        /* Generated patch obtained from the library, should be equal to patch to apply */
        cJSON * generatedPatchedJSON = cJSONUtils_GeneratePatchesCaseSensitive(objectJSON, expectedPatchedJSON);
        if (generatedPatchedJSON != NULL) {
            freeme = cJSON_Print(generatedPatchedJSON);
            printf("Generated patches object from library:\n%s\n", cJSON_Print(generatedPatchedJSON));
            cJSON_free(freeme);
        }
    
        int cJSONPatchStatus = cJSONUtils_ApplyPatchesCaseSensitive(objectJSON, patchesJSON);
        if (cJSONPatchStatus != 0)
        {
            printf("ERROR: cannot apply cJSONUtils_ApplyPatchesCaseSensitive");
        }
        else
        {
            // This will fail because of the { \"op\": \"remove\", \"path\": \"/foo\" } patch
            //freeme = cJSON_Print(objectJSON);
            //printf("Patched object:\n%s\n", cJSON_Print(objectJSON));
            //cJSON_free(freeme);
        }
    
        cJSON_Delete(objectJSON);
        cJSON_Delete(patchesJSON);
        cJSON_Delete(expectedPatchedJSON);
        cJSON_Delete(generatedPatchedJSON);
    
        return 0;
    }
    
    needs-investigation 
    opened by charEtoile 12
  • cJSON get value Improvement Proposal

    cJSON get value Improvement Proposal

    at first, thank you . when i use cJSON get value needed first know it’s correct type and like this Ttem->valueInt to get value. if there some function like cJSON_ItemGetInt, cJSON_ItemGetString so and on . convert type auto . it will be convenient for use.

    opened by yueswing07 11
  • How to get the JSON size before invoke cJSON_PrintPreallocated

    How to get the JSON size before invoke cJSON_PrintPreallocated

    Hi, I have a question about the JSON size. I built a JSON Object and I need to print it into a char buffer allocated dynamically. To allocate the buffer I need to compute the length of the JSON.

    I tried to invoke the cJSON_PrintPreallocated passing a buffer with the exactly size of JSON (computed by hand) but the function fails. If I add an extra 30 byte the cJSON_PrintPreallocated return success.

    Is there a function to create a buffer which length is exactly equal to the size of my JSON?

    Thanks!

    question 
    opened by fedex03 11
  • Support of jsonc

    Support of jsonc

    Hi!

    Microsoft defines a JSON-Format which support comments. The default file extension is jsonc ("c" for comment). It would be nice if cJSON would also support "JSON with comments" (*.jsonc).

    Thanks.

    opened by NehCoy 1
  • cJSON_Parse API detected memory leaks

    cJSON_Parse API detected memory leaks

    for example:

    char *buf = "{\"name\":\"liming\",\"id\":1}";
    cJSON *json;  
    json = cJSON_Parse(buf);
    printf("json = %s\n",json);
    

    the log is:

    json = 
    =================================================================
    ==62255==ERROR: LeakSanitizer: detected memory leaks
    
    Direct leak of 64 byte(s) in 1 object(s) allocated from:
        #0 0x49a7cd in malloc /root/clang-12.0.0/src/compiler-rt/lib/asan/asan_malloc_linux.cpp:145:3
        #1 0x7f640f121d47 in cJSON_New_Item /home/jbh/cJSON/cJSON.c:243:27
        #2 0x7f640f121d47 in cJSON_ParseWithLengthOpts /home/jbh/cJSON/cJSON.c:1114:12
        #3 0x7f640f12b0ac in cJSON_ParseWithOpts /home/jbh/cJSON/cJSON.c:1091:12
        #4 0x7f640f12b0ac in cJSON_Parse /home/jbh/cJSON/cJSON.c:1177:12
        #5 0x4cbb8f in cJSON_Parse_test /home/jbh/cJSON/test.c:262:9
        #6 0x4cbb8f in main /home/jbh/cJSON/test.c:281:5
        #7 0x4ccc35 in __wrap_main /home/jbh/xfuzz-sdk/driver/fast_mode/fast_mode_driver.c:288:20
        #8 0x7f640ed7e0b2 in __libc_start_main /build/glibc-sMfBJT/glibc-2.31/csu/../csu/libc-start.c:308:16
    
    Indirect leak of 128 byte(s) in 2 object(s) allocated from:
        #0 0x49a7cd in malloc /root/clang-12.0.0/src/compiler-rt/lib/asan/asan_malloc_linux.cpp:145:3
        #1 0x7f640f12679e in cJSON_New_Item /home/jbh/cJSON/cJSON.c:243:27
        #2 0x7f640f12679e in parse_object /home/jbh/cJSON/cJSON.c:1637:27
        #3 0x7f640f12679e in parse_value /home/jbh/cJSON/cJSON.c:1360:16
        #4 0x7f640f121e83 in cJSON_ParseWithLengthOpts /home/jbh/cJSON/cJSON.c:1120:10
        #5 0x7f640f12b0ac in cJSON_ParseWithOpts /home/jbh/cJSON/cJSON.c:1091:12
        #6 0x7f640f12b0ac in cJSON_Parse /home/jbh/cJSON/cJSON.c:1177:12
        #7 0x4cbb8f in cJSON_Parse_test /home/jbh/cJSON/test.c:262:9
        #8 0x4cbb8f in main /home/jbh/cJSON/test.c:281:5
        #9 0x4ccc35 in __wrap_main /home/jbh/xfuzz-sdk/driver/fast_mode/fast_mode_driver.c:288:20
        #10 0x7f640ed7e0b2 in __libc_start_main /build/glibc-sMfBJT/glibc-2.31/csu/../csu/libc-start.c:308:16
    
    Indirect leak of 10 byte(s) in 2 object(s) allocated from:
        #0 0x49a7cd in malloc /root/clang-12.0.0/src/compiler-rt/lib/asan/asan_malloc_linux.cpp:145:3
        #1 0x7f640f13fbea in parse_string /home/jbh/cJSON/cJSON.c:812:34
        #2 0x7f640f126938 in parse_object /home/jbh/cJSON/cJSON.c:1660:14
        #3 0x7f640f126938 in parse_value /home/jbh/cJSON/cJSON.c:1360:16
        #4 0x7f640f121e83 in cJSON_ParseWithLengthOpts /home/jbh/cJSON/cJSON.c:1120:10
        #5 0x7f640f12b0ac in cJSON_ParseWithOpts /home/jbh/cJSON/cJSON.c:1091:12
        #6 0x7f640f12b0ac in cJSON_Parse /home/jbh/cJSON/cJSON.c:1177:12
        #7 0x4cbb8f in cJSON_Parse_test /home/jbh/cJSON/test.c:262:9
        #8 0x4cbb8f in main /home/jbh/cJSON/test.c:281:5
        #9 0x4ccc35 in __wrap_main /home/jbh/xfuzz-sdk/driver/fast_mode/fast_mode_driver.c:288:20
        #10 0x7f640ed7e0b2 in __libc_start_main /build/glibc-sMfBJT/glibc-2.31/csu/../csu/libc-start.c:308:16
    
    Indirect leak of 8 byte(s) in 1 object(s) allocated from:
        #0 0x49a7cd in malloc /root/clang-12.0.0/src/compiler-rt/lib/asan/asan_malloc_linux.cpp:145:3
        #1 0x7f640f13fbea in parse_string /home/jbh/cJSON/cJSON.c:812:34
        #2 0x7f640f123257 in parse_value /home/jbh/cJSON/cJSON.c:1345:16
        #3 0x7f640f126d0c in parse_object /home/jbh/cJSON/cJSON.c:1678:14
        #4 0x7f640f126d0c in parse_value /home/jbh/cJSON/cJSON.c:1360:16
        #5 0x7f640f121e83 in cJSON_ParseWithLengthOpts /home/jbh/cJSON/cJSON.c:1120:10
        #6 0x7f640f12b0ac in cJSON_ParseWithOpts /home/jbh/cJSON/cJSON.c:1091:12
        #7 0x7f640f12b0ac in cJSON_Parse /home/jbh/cJSON/cJSON.c:1177:12
        #8 0x4cbb8f in cJSON_Parse_test /home/jbh/cJSON/test.c:262:9
        #9 0x4cbb8f in main /home/jbh/cJSON/test.c:281:5
        #10 0x4ccc35 in __wrap_main /home/jbh/xfuzz-sdk/driver/fast_mode/fast_mode_driver.c:288:20
        #11 0x7f640ed7e0b2 in __libc_start_main /build/glibc-sMfBJT/glibc-2.31/csu/../csu/libc-start.c:308:16
    
    SUMMARY: AddressSanitizer: 210 byte(s) leaked in 6 allocation(s).
    

    Why?

    opened by jjj19950710 1
  • MOX-6029 replace unbounded string operations with safer bounded operations

    MOX-6029 replace unbounded string operations with safer bounded operations

    We've (https://moxion.io) recently upgraded the automated code security audits used to check code commits. The audit flagged several unbounded string operations in cJSON (strcpy). This PR replaces them with the safer bounded functions (strncpy) and lets the code pass security audits.

    opened by harlequin-tech 0
  • cJSON_strdup causes LoadProhibitedCause

    cJSON_strdup causes LoadProhibitedCause

    Hi, After a while that the program runs (about 30 hours) the esp creshes with LoadProhibitedCause and the core dump report that cJSON_strdup (that was call into cJSON_Duplicate) function cannot access memory at address 0x205.

    ================== CURRENT THREAD REGISTERS =================== exccause 0x1c (LoadProhibitedCause) excvaddr 0x205 epc1 0x400da013 epc2 0x0 epc3 0x0 epc4 0x0 epc5 0x0 epc6 0x0 eps2 0x0 eps3 0x0 eps4 0x0 eps5 0x0 eps6 0x0 pc 0x400014dc 0x400014dc lbeg 0x4000c46c 1073792108 lend 0x4000c477 1073792119 lcount 0x0 0 sar 0xe 14 ps 0x60620 394784 threadptr br scompare1 acclo acchi m0 m1 m2 m3 expstate f64r_lo f64r_hi f64s fcr fsr a0 0x800de2b1 -2146573647 a1 0x3ffc6e30 1073507888 a2 0x205 517 a3 0x201 513 a4 0xff 255 a5 0xff00 65280 a6 0xff0000 16711680 a7 0xff000000 -16777216 a8 0x80092060 -2146885536 a9 0x3ffc6e00 1073507840 a10 0x3ffd2c74 1073556596 a11 0x1800 6144 a12 0x3ffaed60 1073409376 a13 0x0 0 a14 0x1 1 a15 0x3ffc4d80 1073499520

    ==================== CURRENT THREAD STACK ===================== #0 0x400014dc in ?? () #1 0x400de2b1 in cJSON_strdup (string=0x205 <error: Cannot access memory at address 0x205>, hooks=0x3ffb13a8 <global_hooks>) at D:/Espressif/esp-idf/components/json/cJSON/cJSON.c:198 #2 0x400df284 in cJSON_Duplicate (item=0x3ffbbdc4, recurse=1) at D:/Espressif/esp-idf/components/json/cJSON/cJSON.c:2721 #3 0x400df2b0 in cJSON_Duplicate (item=, recurse=) at D:/Espressif/esp-idf/components/json/cJSON/cJSON.c:2744 #4 0x400dc6a0 in lora_send (pkt=0x3ffd28cc, send_now=false) at ../main/lora/lora.c:263 #5 0x400db613 in device_get_state (device_id=2, blocking=false, send_now=false) at ../main/device/device.c:347 #6 0x400dba1c in device_task (pvParameters=) at ../main/device/device.c:56 #7 0x4008dead in vPortTaskWrapper (pxCode=0x400db9f0 <device_task>, pvParameters=0x0) at D:/Espressif/esp-idf/components/freertos/port/xtensa/port.c:168

    int lora_send(cJSON *pkt, bool send_now){

    bool pkt_yet_present = false; int pkt_yet_present_position = 1; int pkt_yet_present_pkt_id = 0;

    if(cJSON_GetObjectItem(pkt, "from") &&
    cJSON_GetObjectItem(pkt, "for") &&
    cJSON_GetObjectItem(pkt, "model") &&
    cJSON_GetObjectItem(pkt, "sik") &&
    cJSON_GetObjectItem(pkt, "pkt_id") &&
    cJSON_GetObjectItem(pkt, "datatype") &&
    LORA.pkt_to_send <= 14){

    for (int i = 1; i <= LORA.pkt_to_send; i++) {
      if(JSON_get_number_from_item_debug(LORA.send_pkt_buffer[i],"for", (i+10)) == JSON_get_number_from_item_debug(pkt,"for", (i+20))  && \
         strcmp(JSON_get_string_from_item(LORA.send_pkt_buffer[i],"model"), JSON_get_string_from_item(pkt,"model"))==0       && \
         strcmp(JSON_get_string_from_item(LORA.send_pkt_buffer[i],"datatype"), JSON_get_string_from_item(pkt,"datatype"))==0 ) {
        pkt_yet_present          = true;
        pkt_yet_present_position = i;
        pkt_yet_present_pkt_id   = JSON_get_number_from_item(LORA.send_pkt_buffer[i],"pkt_id");
        break;
      }
      taskYIELD();
    }
    
    
    if (pkt_yet_present == false) {
      cJSON_SetNumberValue(cJSON_GetObjectItem(pkt,"pkt_id"), LORA.pkt_id++);
    
      if (send_now == false) {
        LORA.pkt_to_send++;
        cJSON_Delete(LORA.send_pkt_buffer[LORA.pkt_to_send]);
        LORA.send_pkt_buffer[LORA.pkt_to_send] = cJSON_Duplicate(pkt, true);
      }
      else {
        if (LORA.pkt_to_send == 0) {
          LORA.pkt_to_send++;
          cJSON_Delete(LORA.send_pkt_buffer[LORA.pkt_to_send]);
          LORA.send_pkt_buffer[LORA.pkt_to_send] = cJSON_Duplicate(pkt, true);
        }
        else {
          for (int i = LORA.pkt_to_send; i >= 1; i--) {
            cJSON_Delete(LORA.send_pkt_buffer[i + 1]);
            LORA.send_pkt_buffer[i + 1] = cJSON_Duplicate(LORA.send_pkt_buffer[i], true);
          }
          LORA.pkt_to_send++;
          cJSON_Delete(LORA.send_pkt_buffer[1]);
          LORA.send_pkt_buffer[1] = cJSON_Duplicate(pkt, true);
        }
      }
    
    }
    else if (pkt_yet_present == true) {
      cJSON_SetNumberValue(cJSON_GetObjectItem(pkt,"pkt_id"), pkt_yet_present_pkt_id);
    
      if (send_now == false) {
        cJSON_Delete(LORA.send_pkt_buffer[LORA.pkt_to_send]);
        LORA.send_pkt_buffer[LORA.pkt_to_send] = cJSON_Duplicate(pkt, true);     <------ line 263
      }
      else {
        for (int i = pkt_yet_present_position - 1; i >= 1; i--) {
          cJSON_Delete(LORA.send_pkt_buffer[i + 1]);
          LORA.send_pkt_buffer[i + 1] = cJSON_Duplicate(LORA.send_pkt_buffer[i], true);
        }
        cJSON_Delete(LORA.send_pkt_buffer[1]);
        LORA.send_pkt_buffer[1] = cJSON_Duplicate(pkt, true);
     }
    

    }

    return JSON_get_number_from_item(pkt,"pkt_id");
    

    }else{ return -1; }

    }

    opened by AlgoON-product 2
  • The else branch of the add_item_to_array function affects the function. Apply for the community to roll back this code.

    The else branch of the add_item_to_array function affects the function. Apply for the community to roll back this code.

    1.Problem Description: The else branch of the add_item_to_array function is available in version 1.7.13. In version 1.7.14, this code is deleted, affecting basic functions. The community modification that affects the function is:https://github.com/DaveGamble/cJSON/pull/503/files The code is modified as follows: image 2.Application Scenario: This is a device-cloud synergy scenario: (1) The cloud uses the open-source third-party software com.fasterxml.jackson.databind 2.10.5 to construct a JSON interface message format of HTTPS/HTTP as a request. (2) After the device receives a request message from the cloud, The CJSON 1.7.14 software is used to parse the message in the request and process the response. After the processing, the backend uses the CJSON 1.7.14 software to construct a response message and send the response message to the cloud. 3) The cloud uses the com.fasterxml.jackson.databind 2.10.5 to parse the response message and determine whether the response message is expected.

    After this code segment is deleted, the response message data received by the cloud is changed and the data is lost, affecting service functions.

    3.Suggestions We suggest revert this modification.

    4.Contact: [email protected][email protected][email protected]

    needs-investigation 
    opened by limingjuan00 3
Releases(v1.7.15)
  • v1.7.15(Aug 25, 2021)

    Fixes:

    • Fix potential core dumped for strrchr, see #546
    • Fix null pointer crash in cJSON_CreateXxArray, see #538
    • Fix several null pointer problems on allocation failure, see #526
    • Fix a possible dereference of null pointer, see #519
    • Fix windows build failure about defining nan, see #518
    Source code(tar.gz)
    Source code(zip)
  • v1.7.14(Sep 3, 2020)

    Note:

    Since v1.7.13 changed the stucture of linkedlist to improve the efficiency of adding item to array/object, array->child->prev now is point to tail node, this won't change any behavior except for backward through the linkedlist. The current backward through the linkedlist could be in this way:

    cJSON *last = ...; // the last is known
    cJSON *current_item = last;
    do {
        current_item = current_item->prev;
    } while(current_item != last);
    

    Fixes:

    • optimize the way to find tail node, see #503
    • Fix WError error on macosx because NAN is a float. Thanks @sappo, see #484
    • Fix some bugs in detach and replace. Thanks @miaoerduo, see #456
    Source code(tar.gz)
    Source code(zip)
  • v1.7.13(Apr 2, 2020)

    Features:

    • add new API of cJSON_ParseWithLength without breaking changes. Thanks @caglarivriz, see #358
    • add new API of cJSON_GetNumberValue. Thanks @Intuition, see#385
    • add uninstall target function for CMake. See #402
    • Improve performance of adding item to array. Thanks @xiaomianhehe, see #430, #448
    • add new API of cJSON_SetValuestring, for changing the valuestring safely. See #451
    • add return value for cJSON_AddItemTo... and cJSON_ReplaceItem... (check if the operation successful). See #453

    Fixes:

    • Fix clang -Wfloat-equal warning. Thanks @paulmalovanyi, see #368
    • Fix make failed in mac os. See #405
    • Fix memory leak in cJSONUtils_FindPointerFromObjectTo. Thanks @andywolk for reporting, see #414
    Source code(tar.gz)
    Source code(zip)
  • v1.7.12(May 16, 2019)

    Fixes:

    • Fix infinite loop in cJSON_Minify (potential Denial of Service), thanks @Alanscut for reporting. See #354
    • Fix link error for Visual Studio. Thanks @tan-wei, see #352
    • Undefine true and false for cJSON_Utils before redefining them. Thanks @raiden00pl, see #347
    Source code(tar.gz)
    Source code(zip)
  • v1.7.11(Apr 14, 2019)

    Fixes:

    • Fix a bug where cJSON_Minify could overflow it's buffer, both reading and writing. This is a security issue. (see #338). Big thanks @bigric3 for reporting.
    • Unset true and false macros before setting them if they exist. See #339, thanks @raiden00pl for reporting
    Source code(tar.gz)
    Source code(zip)
  • v1.7.10(Dec 20, 2018)

    Fixes:

    • Fix package config file for libcjson. Thanks @shiluotang for reporting (#321)
    • Correctly split lists in cJSON_Utils's merge sort. Thanks @andysCaplin for the fix (#322)
    Source code(tar.gz)
    Source code(zip)
  • v1.7.9(Dec 16, 2018)

    Fixes:

    • Fix a bug where cJSON_GetObjectItemCaseSensitive would pass a nullpointer to strcmp when called on an array (#315). Thanks @yuweol for reporting.
    • Fix error in cJSON_Utils where the case sensitivity was not respected (#317). Thanks @yuta-oxo for fixing.
    • Fix some warnings detected by the Visual Studio Static Analyzer (#307). Thanks @bnason-nf
    Source code(tar.gz)
    Source code(zip)
  • v1.7.8(Sep 21, 2018)

  • v1.7.7(May 21, 2018)

    Fixes:

    • Fix a memory leak when realloc fails (see #267), thanks @AlfieDeng for reporting
    • Fix a typo in the header file (see #266), thanks @zhaozhixu
    Source code(tar.gz)
    Source code(zip)
  • v1.7.6(Apr 13, 2018)

    Fixes:

    • Add SONAME to the ELF files built by the Makefile (see #252), thanks @YanhaoMo for reporting
    • Add include guards and extern "C" to cJSON_Utils.h (see #256), thanks @daschfg for reporting

    Other changes:

    • Mark the Makefile as deprecated in the README.
    Source code(tar.gz)
    Source code(zip)
  • v1.7.5(Mar 22, 2018)

  • v1.7.4(Mar 2, 2018)

    Fixes:

    • Fix potential use after free if the string parameter to cJSON_AddItemToObject is an alias of the string property of the object that is added (#248). Thanks @hhallen for reporting.
    Source code(tar.gz)
    Source code(zip)
  • v1.7.3(Feb 7, 2018)

  • v1.7.2(Feb 6, 2018)

  • v1.7.1(Jan 9, 2018)

    Fixes:

    • Fixed an Off-By-One error that could lead to an out of bounds write. Thanks @liuyunbin for reporting (see #230)
    • Fixed two errors with buffered printing. Thanks @liuyunbin for reporting (see #230)
    Source code(tar.gz)
    Source code(zip)
  • v1.7.0(Dec 31, 2017)

    Features:

    • Large rewrite of the documentation, see #215
    • Added the cJSON_GetStringValue function
    • Added the cJSON_CreateStringReference function
    • Added the cJSON_CreateArrayReference function
    • Added the cJSON_CreateObjectReference function
    • The cJSON_Add...ToObject macros are now functions that return a pointer to the added item, see #226

    Fixes:

    • Fix a problem with GNUInstallDirs in the CMakeLists.txt, thanks @yangfl, see #210
    • Fix linking the tests when building as static library, see #213
    • New overrides for the CMake option BUILD_SHARED_LIBS, see #207

    Other Changes:

    • Readme: Explain how to include cJSON, see #211
    • Removed some trailing spaces in the code, thanks @yangfl, see #212
    • Updated Unity and json-patch-tests
    Source code(tar.gz)
    Source code(zip)
  • v1.6.0(Oct 8, 2017)

    Features:

    • You can now build cJSON as both shared and static library at once with CMake using -DBUILD_SHARED_AND_STATIC_LIBS=On, see #178
    • UTF-8 byte order marks are now ignored, see #184
    • Locales can now be disabled with the option -DENABLE_LOCALES=Off, see #202, thanks @Casperinous
    • Better support for MSVC and Visual Studio

    Other Changes:

    • Add the new warnings -Wswitch-enum, -Wused-but-makred-unused, -Wmissing-variable-declarations, -Wunused-macro
    • More number printing tests.
    • Continuous integration testing with AppVeyor (semi automatic at this point), thanks @simon-p-r
    Source code(tar.gz)
    Source code(zip)
  • v1.5.9(Sep 8, 2017)

  • v1.5.8(Aug 21, 2017)

  • v1.5.7(Jul 12, 2017)

    Fixes:

    • Fix a bug where realloc failing would return a pointer to an invalid memory address. This is a security issue as it could potentially be used by an attacker to write to arbitrary memory addresses. (see #189), fixed in (954d61e5e7cb9dc6c480fc28ac1cdceca07dd5bd), big thanks @timothyjohncarney for reporting this issue
    • Fix a spelling mistake in the AFL fuzzer dictionary (#185), thanks @jwilk
    Source code(tar.gz)
    Source code(zip)
  • v1.5.6(Jun 28, 2017)

    Fixes:

    • Make cJSON a lot more tolerant about passing NULL pointers to its functions, it should now fail safely instead of dereferencing the pointer. (#183) Thanks @msichal for reporting #182
    Source code(tar.gz)
    Source code(zip)
  • v1.5.5(Jun 14, 2017)

    Fixes:

    • Fix pointers to nested arrays in cJSON_Utils (9abe75e072050f34732a7169740989a082b65134)
    • Fix an error with case sensitivity handling in cJSON_Utils (b9cc911831b0b3e1bb72f142389428e59f882b38)
    • Fix cJSON_Compare for arrays that are prefixes of the other and objects that are a subset of the other (03ba72faec115160d1f3aea5582d9b6af5d3e473) See #180, thanks @zhengqb for reporting
    Source code(tar.gz)
    Source code(zip)
  • v1.5.4(Jun 4, 2017)

    Fixes:

    • Fix build with GCC 7.1.1 and optimization level -O2 (bfbd8fe0d85f1dd21e508748fc10fc4c27cc51be)

    Other Changes:

    • Update Unity to 3b69beaa58efc41bbbef70a32a46893cae02719d
    Source code(tar.gz)
    Source code(zip)
  • v1.5.3(May 22, 2017)

  • v1.5.2(May 10, 2017)

    Fixes:

    • Fix a reading buffer overflow in parse_string (a167d9e381e5c84bc03de4e261757b031c0c690d)
    • Fix compiling with -Wcomma (186cce3ece6ce6dfcb58ac8b2a63f7846c3493ad)
    • Remove leftover attribute from tests (b537ca70a35680db66f1f5b8b437f7114daa699a)
    Source code(tar.gz)
    Source code(zip)
  • v1.5.1(May 6, 2017)

    Fixes:

    • Add gcc version guard to the Makefile (#164), thanks @juvasquezg
    • Fix incorrect free in cJSON_Utils if custom memory allocator is used (#166), thanks @prefetchnta
    Source code(tar.gz)
    Source code(zip)
  • v1.5.0(May 2, 2017)

    Features:

    • cJSON finally prints numbers without losing precision (#153) thanks @DeboraG
    • cJSON_Compare recursively checks if two cJSON items contain the same values (#148)
    • Provide case sensitive versions of every function where it matters (#158, #159)
    • Added cJSON_ReplaceItemViaPointer and cJSON_DetachItemViaPointer
    • Added cJSON_free and cJSON_malloc that expose the internal configured memory allocators. (02a05eea4e6ba41811f130b322660bea8918e1a0)

    Enhancements:

    • Parse into a buffer, this will allow parsing \u0000 in the future (not quite yet though)
    • General simplifications and readability improvements
    • More unit tests
    • Update unity testing library to 2.4.1
    • Add the json-patch-tests test suite to test cJSON_Utils.
    • Move all tests from test_utils.c to unit tests with unity.

    Fixes:

    • Fix some warnings with the Microsoft compiler (#139) thanks @PawelWMS
    • Fix several bugs in cJSON_Utils, mostly found with json-patch-tests
    • Prevent a stack overflow by specifying a maximum nesting depth CJSON_NESTING_LIMIT
    Source code(tar.gz)
    Source code(zip)
  • v1.4.7(Apr 18, 2017)

    Fixes:

    • Fix cJSONUtils_ApplyPatches, it was completely broken and apparently nobody noticed (or at least reported it) (075a06f40bdc4f836c7dd7cad690d253a57cfc50)
    • Fix inconsistent prototype for cJSON_GetObjectItemCaseSensitive (51d3df6c9f7b56b860c8fb24abe7bab255cd4fa9) thanks @PawelWMS
    Source code(tar.gz)
    Source code(zip)
  • v1.4.6(Apr 8, 2017)

    Fixes:

    • Several corrections in the README
    • Making clear that valueint should not be written to
    • Fix overflow detection in ensure (2683d4d9873df87c4bdccc523903ddd78d1ad250)
    • Fix a potential null pointer dereference in cJSON_Utils (795c3acabed25c9672006b2c0f40be8845064827)
    • Replace incorrect sizeof('\0') with sizeof("") (84237ff48e69825c94261c624eb0376d0c328139)
    • Add caveats section to the README (50b3c30dfa89830f8f477ce33713500740ac3b79)
    • Make cJSON locale independent (#146) Thanks @peterh for reporting
    • Fix compiling without CMake with MSVC (#147) Thanks @dertuxmalwieder for reporting
    Source code(tar.gz)
    Source code(zip)
  • v1.4.5(Mar 28, 2017)

    Fixes:

    • Fix bug in cJSON_SetNumberHelper, thanks @mmkeeper (#138 ef34500693e8c4a2849d41a4bd66fd19c9ec46c2)
    • Workaround for internal compiler error in GCC 5.4.0 and 6.3.1 on x86 (2f65e80a3471d053fdc3f8aed23d01dd1782a5cb GCC bugreport)
    Source code(tar.gz)
    Source code(zip)
Owner
Dave Gamble
Dave Gamble
A C++, header-only library for constructing JSON and JSON-like data formats, with JSON Pointer, JSON Patch, JSON Schema, JSONPath, JMESPath, CSV, MessagePack, CBOR, BSON, UBJSON

JSONCONS jsoncons is a C++, header-only library for constructing JSON and JSON-like data formats such as CBOR. For each supported data format, it enab

Daniel Parker 492 May 9, 2022
Very low footprint JSON parser written in portable ANSI C

Very low footprint JSON parser written in portable ANSI C. BSD licensed with no dependencies (i.e. just drop the C file into your project) Never recur

James McLaughlin 1.1k May 8, 2022
Very low footprint JSON parser written in portable ANSI C

Very low footprint JSON parser written in portable C89 (sometimes referred to as ANSI C). BSD licensed with no dependencies (i.e. just drop the C file

null 1.2k May 12, 2022
JSON parser and generator for C/C++ with scanf/printf like interface. Targeting embedded systems.

JSON parser and emitter for C/C++ Features ISO C and ISO C++ compliant portable code Very small footprint No dependencies json_scanf() scans a string

Cesanta Software 604 May 12, 2022
JSON & BSON parser/writer

jbson is a library for building & iterating BSON data, and JSON documents in C++14. \tableofcontents Features # {#features} Header only. Boost license

Chris Manning 38 Feb 18, 2022
Jsmn is a world fastest JSON parser/tokenizer. This is the official repo replacing the old one at Bitbucket

JSMN jsmn (pronounced like 'jasmine') is a minimalistic JSON parser in C. It can be easily integrated into resource-limited or embedded projects. You

Serge Zaitsev 2.9k May 17, 2022
A JSON parser in C++

JSON++ Introduction JSON++ is a light-weight JSON parser, writer and reader written in C++. JSON++ can also convert JSON documents into lossless XML d

Hong Jiang 481 Apr 29, 2022
🗄️ single header json parser for C and C++

??️ json.h A simple single header solution to parsing JSON in C and C++. JSON is parsed into a read-only, single allocation buffer. The current suppor

Neil Henning 495 May 18, 2022
Very simple C++ JSON Parser

Very simple JSON parser for c++ data.json: { "examples": [ { "tag_name": "a", "attr": [ { "key":

Amir Saboury 64 May 12, 2022
a JSON parser and printer library in C. easy to integrate with any model.

libjson - simple and efficient json parser and printer in C Introduction libjson is a simple library without any dependancies to parse and pretty prin

Vincent Hanquez 259 May 14, 2022
a header-file-only, JSON parser serializer in C++

PicoJSON - a C++ JSON parser / serializer Copyright © 2009-2010 Cybozu Labs, Inc. Copyright © 2011-2015 Kazuho Oku Licensed under 2-clause BSD license

Kazuho Oku 998 May 12, 2022
A fast JSON parser/generator for C++ with both SAX/DOM style API

A fast JSON parser/generator for C++ with both SAX/DOM style API Tencent is pleased to support the open source community by making RapidJSON available

Tencent 12k May 14, 2022
Lightweight, extremely high-performance JSON parser for C++11

sajson sajson is an extremely high-performance, in-place, DOM-style JSON parser written in C++. Originally, sajson meant Single Allocation JSON, but i

Chad Austin 532 Apr 30, 2022
🔋 In-place lightweight JSON parser

?? JSON parser for C This is very simple and very powerful JSON parser. It creates DOM-like data structure and allows to iterate and process JSON obje

Recep Aslantas 20 May 5, 2022
RapidJSON is a JSON parser and generator for C++.

A fast JSON parser/generator for C++ with both SAX/DOM style API

Tencent 12k May 14, 2022
single-header json parser for c99 and c++

ghh_json.h a single-header ISO-C99 (and C++ compatible) json loader. why? obviously this isn't the first json library written for C, so why would I wr

garrison hinson-hasty 14 May 10, 2022
Buggy JSON parser

Fuzzgoat: A minimal libFuzzer integration This repository contains a basic C project that includes an (intentionally insecure) JSON parser. It is an e

Fuzzbuzz 1 Apr 11, 2022
A generator of JSON parser & serializer C++ code from structure header files

JSON-CPP-gen This is a program that parses C++ structures from a header file and automatically generates C++ code capable of serializing said structur

Viktor Chlumský 8 May 2, 2022
json-cpp is a C++11 JSON serialization library.

JSON parser and generator for C++ Version 0.1 alpha json-cpp is a C++11 JSON serialization library. Example #include <json-cpp.hpp> struct Foo {

Anatoly Scheglov 4 Dec 31, 2019