在读取 JSON 数组元素时使用 cJSON 问题

Using cJSON issue in reading JSON array elements

我正在编写一小段 c 代码来使用 gcc 中的 cJSON 库解析 json 数组元素。 解析成功,但数组元素的打印结果为空。 不确定是什么问题。

需要通过json src、dst 和设备索引列表的数组输入。

https://jsonlint.com/ 验证的输出

第一个数据:

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

第二个数据:

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

文件路径&编译方式

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

代码:

#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);
}   

输出:

第一次尝试: [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

第二次尝试:

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

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

您的主要问题是您调用的是 cJSON_GetArrayItem 而不是 cJSON_GetObjectItem。属性是对象的一部分,而不是包含数组的直接部分。切换调用,您显示的代码将大部分起作用。

其他次要内容:

  • 您缺少 #include <string.h> strlen
  • 您在打印 strlen 的结果时使用了 %d。由于 strlen returns 和 size_t,您应该使用 %zu 代替。
  • 您将 jsrcPidjdstPidjdevIdxs 打印为字符串 (%s),但它们实际上是 struct cJSON *,因此您应该使用%p 并转换为 (void*).

如果您启用警告,编译器可能会告诉您所有这些。使用 GCC 时,始终使用标志 -Wall -Wextra -Wpedantic。另外,通过给出 -std=c90-std=c99-std=c11-std=c18.

之一告诉编译器您使用的是哪个 C 标准