Search code examples
ccjson

Using cJSON issue in reading JSON array elements


I am writing a small piece of c code to parse json array elements using cJSON library in gcc. The parsing is successful but printing of array elements turn up as null. Not sure what is the issue.

Need to pass json array input of src, dst and list of device indexes.

output of https://jsonlint.com/ validation

First data:

{
    "NPCDevMoveReqList": [{
            "srcPid": "1",
            "destPid": "2",
            "devIdxs": ["1", "2", "3"]
        },
        {
            "srcPid": "1",
            "destPid": "3",
            "devIdxs": ["4", "5", "6"]
        }
    ]
} 

Second data:

{
    "NPCDevMoveReqList": [{
        "srcPid": 1,
        "destPid": 2,
        "devIdxs": [1, 2, 3]
    }]
}

File path & compilation method

/home/ccode/jsonchk.c
/home/ccode/cJSON
gcc -L cJSON/ -lcjson jsonchk.c -o jsonchkary.o
export LD_LIBRARY_PATH=/home/ccode/cJSON

Code:

#include "stdio.h"
#include "cJSON/cJSON.h"
#define REASON_INPUTVALUES_JSONPARSER_ERROR 21
//
///home/ccode/jsonchk.c
//gcc -L cJSON/ -lcjson jsonchk.c -o jsonchk.o
//export LD_LIBRARY_PATH=/home/ccode/cJSON
//

int parsejsonstr(void)
{
    char jsoninput[500] = { 0 };
    snprintf( (char *)jsoninput, sizeof(jsoninput), 
"{\"NPCDevMoveReqList\":[{\"srcPid\":\"1\",\"destPid\":\"2\",\"devIdxs\":[\"1\",\"2\",\"3\"]},{\"srcPid\":\"1\",\"destPid\":\"3\",\"devIdxs\":[\"4\",\"5\",\"6\"]}]}");

    printf("jsonstrinput>>:%s\n", jsoninput);


    cJSON *jSON_devmove_data = cJSON_Parse(jsoninput);
    if(jSON_devmove_data == NULL)
    {
        printf("\nError moveDevicesJsonArray mvJsonArrayBuf:%.24s mvJsonArrayBuf:%d main parsefail",
                            jsoninput, strlen(jsoninput));
        return REASON_INPUTVALUES_JSONPARSER_ERROR;
    }

    cJSON * json_devmove_reqlist = cJSON_GetObjectItem(jSON_devmove_data, "NPCDevMoveReqList");
    if(jSON_devmove_data == NULL)
    {
        printf("\nError moveDevicesJsonArray mvJsonArrayBuf:%.24s mvJsonArrayBuf:%d reqlist parsefail", 
                                jsoninput, strlen(jsoninput));
        return REASON_INPUTVALUES_JSONPARSER_ERROR;
    }

    int idx=0;
    cJSON* jsrcPid = NULL;
    cJSON* jdstPid = NULL;
    cJSON* jdevIdxs = NULL;

    for (idx = 0 ; idx < cJSON_GetArraySize(json_devmove_reqlist) ; idx++)
    {
        cJSON * json_subitem = cJSON_GetArrayItem(json_devmove_reqlist, idx);
        if(json_subitem == NULL)
        {
            printf("\nError moveDevicesJsonArray mvJsonArrayBuf:%.24s mvJsonArrayBuf:%d idxsub parsefail", 
                                    jsoninput, strlen(jsoninput));
            return REASON_INPUTVALUES_JSONPARSER_ERROR;
        }

        jsrcPid = cJSON_GetArrayItem(json_subitem, "srcPid"); 
        jdstPid = cJSON_GetArrayItem(json_subitem,"destPid");
            jdevIdxs = cJSON_GetArrayItem(json_subitem, "devIdxs");

        printf("\n>>>moveDevicesJsonArray aryidx:%d src:%s dst:%s devidxs:%s <<\n",
            idx, jsrcPid, jdstPid, jdevIdxs);           
    }


    return 1;
}


void main(void)
{
    int rval = parsejsonstr();
    printf("jsonparsestr call res>>:%d\n", rval);
}   

Output:

First try: [ccode]$ ./jsonchkary.o jsonstrinput>>:{"NPCDevMoveReqList":[{"srcPid":"1","destPid":"2","devIdxs":["1","2","3"]},{"srcPid":"1","destPid":"3","devIdxs":["4","5","6"]}]}

>>>moveDevicesJsonArray aryidx:0 src:(null) dst:(null) devidxs:(null) <<

>>>moveDevicesJsonArray aryidx:1 src:(null) dst:(null) devidxs:(null) <<
jsonparsestr call res>>:1

Second try:

[ccode]$ ./jsonchkary.o
jsonstrinput>>:{"NPCDevMoveReqList":[{"srcPid":1,"destPid":2,"devIdxs":[1,2,3]}]}

>>>moveDevicesJsonArray aryidx:0 src:(null) dst:(null) devidxs:(null) <<

Solution

  • Your main problem is that you are calling cJSON_GetArrayItem instead of cJSON_GetObjectItem. The properties are part of an object, not directly part of the containing array. Switch the calls and the code you have shown will mostly work.

    Other, minor stuff:

    • You are missing #include <string.h> for strlen.
    • You are using %d when printing the result of strlen. Since strlen returns a size_t, you should use %zu instead.
    • You are printing jsrcPid, jdstPid, and jdevIdxs as strings (%s), but they are actually struct cJSON *, so you should use %p and cast to (void*).

    The compiler could have told you about all of these, had you enabled warnings. When using GCC, always use the flags -Wall -Wextra -Wpedantic. Also, tell the compiler which C standard you using by giving one of -std=c90, -std=c99, -std=c11 or -std=c18.