cJSON复习笔记

近期需要应用cJSON,其实多年前使用过cJSON,基本全忘记了,特此针对以前代码复习记录。

下面是一个cJSON的基本结构体

/* The cJSON structure: */
typedef struct cJSON
{
    /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
    struct cJSON *next;
    struct cJSON *prev;
    /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
    struct cJSON *child;

    /* The type of the item, as above. */
    int type;

    /* The item's string, if type==cJSON_String  and type == cJSON_Raw */
    char *valuestring;
    /* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
    int valueint;
    /* The item's number, if type==cJSON_Number */
    double valuedouble;

    /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
    char *string;
} cJSON;

JSON基本组成:
JSON具有以下这些形式:
对象是一个无序的“‘名称/值’对”集合。一个对象以 {左括号 开始, }右括号 结束。每个“名称”后跟一个 :冒号 ;“‘名称/值’ 对”之间使用 ,逗号 分隔。

基本用法举例:
A 一个开锁命令应答的例子:CMDSet_Ack_Lock(“lock” , “ok”,door_id);

1、定义一个cJSON型指针cJSON * pJsonRoot = NULL; 创建一个cJSON对象pJsonRoot = cJSON_CreateObject();这样就建立了一个基本的cJSON object:pJsonRoot
{
“”
}
事实上cJSON可创建为单一对象Object、Raw、阵列Array、整型阵列IntArray、浮点型阵列FloatArray、字符串型阵列StringArray等,我们简单使用就用单一对象即可,其它不做探讨。
2、由于还要用到一个子对象,因此定义一个cJSON型指针cJSON * pSubJson = NULL;
创建一个cJSON对象pSubJson = cJSON_CreateObject();作为子jSON对象pSubJson
{
“”
}
3、先往子对象里面添加项目
先添加字符串{“lock”:”ok”}:cJSON_AddStringToObject(pSubJson, (const char*)cmd , (const char*)result);结果为:{“lock”:”ok”}
4、将控制结果(就是上一步子对象)作为子项目添加到pJsonRoot,项目名称
”ack”:cJSON_AddItemToObject(pJsonRoot, “ack”, pSubJson);结果为:
{
“ack”:{“lock”:”ok”}
}
5、将门锁编号(整型)添加到pJsonRoot,项目名称
”door_id”:cJSON_AddNumberToObject(pJsonRoot, “door_id”,3);结果变为:
{
“ack”:{“lock”:”ok”},
“door_id”:3
}
6、将设备编号(字符串型)添加到pJsonRoot,项目名称
”deviceid”,cJSON_AddStringToObject(pJsonRoot, “deviceid”,(const char*)PRODUCT_ID);结果变为:
{
“ack”:{“lock”:”ok”},
“door_id”:3,
“deviceid”:” 008605710100172601”
}
7、将服务端指令编号(字符串型)添加到pJsonRoot, 项目名称
”traceid”,cJSON_AddStringToObject(pJsonRoot, “traceid”,(const char*)TraceID);结果变为:
{
“ack”:{“lock”:”ok”},
“door_id”:3,
“deviceid”:” 008605710100172601”,
“traceid”:”1001”
}
8、cJSON对象内部项目组装完成后,打印为可发送的整型数组(指针)pPrintData = (INT8U*)cJSON_Print(pJsonRoot);实际为放到一段内存空间,发送后需释放内存。
9、发送CJSON_SEND(pPrintData , strlen((const char*)pPrintData));
10、删除cJSON_Delete(pJsonRoot);
11、释放内存tlsf_free(pPrintData);

B 一个同时开关多个LED灯的例子:static INT16S Led_Parse(cJSON root)
1、定义要用的cJSON格式(名称上反映出多个灯控制的指令应该是阵列格式)cJSON
pJsonArray = NULL; 查询到名称”led”,pJsonArray = cJSON_GetObjectItem(root, “led”);
2、获取阵列元素数量INT16U array_size = cJSON_GetArraySize(pJsonArray);
3、然后依次获取每个元素的项目,
for(int i = 0; i < array_size; i++)
{ cJSON * ArrayItem = cJSON_GetArrayItem(pJsonArray, i);}
4、内部再定义一个用来解析的cJSON指针变量cJSON* ObjectItem = NULL;
5、依次获取阵列中的对象,ObjectItem = cJSON_GetObjectItem(ArrayItem , Led_ArrayItemKey[i]);其中Led_ArrayItemKey是预先定义好的静态变量
const char* Led_ArrayItemKey[] =
{
“led1”,
“led2”,
“led3”,
};
6、判断对象的字符串进行相应控制并且作出应答

if(ObjectItem)  
{  
    if(strcmp(ObjectItem->valuestring , "on") == 0)
    {
        DTU_Drv.IO->DOSet(Led_Portx[i]);
        err = CJSON_PARSE_ERR_NONE;
    }
    else if(strcmp(ObjectItem->valuestring , "off") == 0)
    {
        DTU_Drv.IO->DOReset(Led_Portx[i]);
        err = CJSON_PARSE_ERR_NONE;
    }
    
    if(err == CJSON_PARSE_ERR_NONE)
        CMDSet_Ack(ObjectItem->string  , "ok");
    else
        CMDSet_Ack(ObjectItem->string  , "fail");
}  

C 收到数据后开始解析的步骤
1、由于需要获取整体cJSON、命令数据、控制路径数据,先定义三个cJSON指针 cJSON *pJsonRoot = NULL;cJSON *pJsonObjectItem = NULL;cJSON pJsonObject = NULL;
2、解析整个数据包,解析成cJSON格式,pJsonRoot = cJSON_Parse(pData);
3、尝试依次查询各个命令项目,若查询到,再进行后续操作
for(INT8U i = 0 ; i < sizeof(cJSON_CMD_Set)/sizeof(cJSON_CMD_Set_t) ; i++)
{
pJsonObjectItem = cJSON_GetObjectItem(pJsonRoot, (const char
)cJSON_CMD_Set[i].CMD);
}
其中cJSON_CMD_Set[i].CMD已经预先进行了定义

cJSON_CMD_Set_t cJSON_CMD_Set[] = 
{
	//down
	{"infomation" , JSON_CMD_TYPE_OBJECT , JSON_CMD_DIR_DOWN , Infomation_Parse},
	{"lock" , JSON_CMD_TYPE_ARRAY , JSON_CMD_DIR_DOWN , Lock_Parse},
	{"scanner" , JSON_CMD_TYPE_OBJECT , JSON_CMD_DIR_DOWN , scanner_Parse},
	{"eraser" , JSON_CMD_TYPE_OBJECT , JSON_CMD_DIR_DOWN , Earser_Parse},
	{"led" , JSON_CMD_TYPE_ARRAY , JSON_CMD_DIR_DOWN , Led_Parse},
	{"ip" , JSON_CMD_TYPE_OBJECT , JSON_CMD_DIR_DOWN , NULL},
	{"reset" , JSON_CMD_TYPE_OBJECT , JSON_CMD_DIR_DOWN , Reset_Parse},
	{"factoryset" , JSON_CMD_TYPE_OBJECT , JSON_CMD_DIR_DOWN , NULL},

};

4、若查询到,再进行后续操作

if(pJsonObjectItem)
{
    if(cJSON_CMD_Set[i].callback)//如果有回调函数
    {
        pJsonObject = cJSON_GetObjectItem(pJsonRoot, (const char*)"traceid");//查询traceid
        if(pJsonObject)
            strcpy(TraceID , pJsonObject->valuestring);
        else
            memset(TraceID , 0 ,sizeof(TraceID));
        
		//判断命令类型是阵列还是单一对象,而后进入具体回调函数处理
        if(cJSON_CMD_Set[i].Type == JSON_CMD_TYPE_ARRAY)
            cJSON_CMD_Set[i].callback(pJsonRoot);
        else
            cJSON_CMD_Set[i].callback(pJsonObjectItem);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值