文章摘要: 本文主要对单片机及Linux中对cjson库的应用,进行了详细说明。
通过验证,对于封装json格式,调用cjson库并不好用,还不如sprintf拼接更省事,特别对于浮点型小数,解析格式倒是不错。


Linux应用

安装cjson库:

sudo apt-get install libcjson-dev

编译选项: -lcjson


单片机:
下载cjson源码:https://github.com/arnoldlu/cJSON
只需将cJSON.h/cJSON.c代码加入工程编译即可。


cJSON_CreateObject():创建一个json数据结点;
cJSON_AddStringToObject():添加一个字符串数据;
cJSON_AddNumberToObject():添加一个数值数据;
cJSON_AddItemToObject():添加一个json项目;
cJSON_CreateArray():添加一个json数组;
cJSON_Print():转换json数据为字符串;
cJSON_Delete():销毁json数据,注意通过cJSON_Parse()创建的json数据中分配了堆存储,必须通过cJSON_Delete()注销才能释放空间;


示例代码: encode.c

#include <stdio.h>
#include "cJSON.h"
int main()
{
    cJSON * root =  cJSON_CreateObject();
    cJSON * item =  cJSON_CreateObject();
    cJSON * next =  cJSON_CreateObject();
 
    // 根节点下添加
    cJSON_AddItemToObject(root, "rc",        cJSON_CreateNumber(0));
    cJSON_AddItemToObject(root, "operation", cJSON_CreateString("CALL"));
    cJSON_AddItemToObject(root, "service",   cJSON_CreateString("telephone"));
    cJSON_AddItemToObject(root, "text",      cJSON_CreateString("打电话给张三"));
    
    //root节点下添加semantic子节点
    cJSON_AddItemToObject(root, "semantic", item);
    
    //semantic节点下添加item子节点
    cJSON_AddItemToObject(item, "slots", next);
    //添加name节点
    cJSON_AddItemToObject(next, "name", cJSON_CreateString("张三"));
 
    printf("%s\n", cJSON_Print(root));
 
    return 0;
}

执行结果:

{
        "rc":   0,
        "operation":    "CALL",
        "service":      "telephone",
        "text": "打电话给张三",
        "semantic": {
                "slots":{
                        "name": "张三"
                }
        }
}

decode.c

#include <stdio.h>
#include <stdlib.h>
#include "cJSON.h"

// 以递归的方式打印json的最内层键值对 
void printJson(cJSON * root)
{
    for(int i=0; i<cJSON_GetArraySize(root); i++)   //遍历最外层json键值对
    {
        cJSON * item = cJSON_GetArrayItem(root, i);        
        if(cJSON_Object == item->type)      //如果对应键的值仍为cJSON_Object就递归调用printJson
        {
            printf("----------------------\r\n");
            printJson(item);    // 递归
        }
        else                                //值不为json对象就直接打印出键和值
        {
            printf("%s->", item->string);
            printf("%s\n", cJSON_Print(item));
        }
    }
}
 
int main()
{
    char * jsonStr = "{\"semantic\":{\"slots\":{\"name\":\"张三\"}}, \"rc\":0, \"operation\":\"CALL\", \"service\":\"telephone\", \"text\":\"打电话给张三\"}";
    cJSON * root = NULL;
    cJSON * item = NULL;//cjson对象
 
    root = cJSON_Parse(jsonStr);     
    if (!root) 
    {
        printf("Error before: [%s]\n",cJSON_GetErrorPtr());
    }
    else
    {
        printf("%s\n", "有格式的方式打印Json:");           
        printf("%s\n\n", cJSON_Print(root));
 #if 0       
        printf("%s\n", "无格式方式打印json:");
        printf("%s\n\n", cJSON_PrintUnformatted(root));
 #endif
        printf("%s\n", "一步一步的获取name 键值对:");
        printf("%s\n", "获取semantic下的cjson对象:");
        item = cJSON_GetObjectItem(root, "semantic");//
        printf("%s\n", cJSON_Print(item));
        printf("%s\n", "获取slots下的cjson对象");
        item = cJSON_GetObjectItem(item, "slots");
        printf("%s\n", cJSON_Print(item));
        printf("%s\n", "获取name下的cjson对象");
        item = cJSON_GetObjectItem(item, "name");
        printf("%s\n", cJSON_Print(item));
 
        printf("%s:", item->string);   //看一下cjson对象的结构体中这两个成员的意思
        printf("%s\n", item->valuestring);                        
 
        printf("\n%s\n", "打印json所有最内层键值对:");
        printJson(root);
    }
    return 0;    
}