STM32之cJSON的打包和解析
最近在学习STM32,由于需要传输较多的参数因此想到json,虽然keil自带了json包,但是我还是想使用cjson,因为以前我在ESP8266上面也用到过。
cJSON的配置使用也很简单,如何把cJSON加入工程可以看这里https://blog.csdn.net/yannanxiu/article/details/52712078
使用test文件编译通过后,鉴于test里面的程序太复杂,我开始尝试删掉自己重新写。
文章最后机翻了下cJSON.h里面的一些函数
下面是cJSON的结构体
/*The cJSON结构 */
typedef struct cJSON
{
/* next / prev允许您遍历数组/对象链。或者,使用GetArraySize /GetArrayItem //GetObjectItem */
struct cJSON *next;
struct cJSON *prev;
struct cJSON *child;// 数组或对象的子节点。
int type;// 项目的类型,如上所述.
char *valuestring;//字符串
int valueint;//整数值
double valuedouble;//浮点值
char *string;//项目的名称字符串,如果此项目是子项,或者在对象的子项列表中。
} cJSON;
1.使用cJSON库打包
json打包就是先创建一个数据包,然后往里面添加数据
#include <stdio.h>
#include <stdlib.h>
#include "cJSON.h"
#include "test.h"
int cJSON_main(void)
{
cJSON * json = cJSON_CreateObject();//创建数据包
cJSON * item = cJSON_CreateObject();//创建数据包(二级)
cJSON_AddItemToObject(json, "group", cJSON_CreateString("noble team"));//添加数据
cJSON_AddItemToObject(json, "member", item);//在json下添加子集item
cJSON_AddItemToObject(item, "noble1", cJSON_CreateString("卡特-A259"));//给item添加数据
cJSON_AddItemToObject(item, "noble2", cJSON_CreateString("凯瑟琳-B320"));
cJSON_AddItemToObject(item, "noble3", cJSON_CreateString("俊-A266"));
cJSON_AddItemToObject(item, "noble4", cJSON_CreateString("埃米尔-A239"));
cJSON_AddItemToObject(item, "noble5", cJSON_CreateString("乔治-052"));
cJSON_AddItemToObject(item, "noble6", cJSON_CreateString("斯巴达-B312"));
printf("%s\n", cJSON_Print(json));
cJSON_Delete(json);//释放内存
cJSON_Delete(item);
}
输出结果
{
"group": "noble team",
"member": {
"noble1": "卡特-A259",
"noble2": "凯瑟琳-B320",
"noble3": "俊-A266",
"noble4": "埃米尔-A239",
"noble5": "乔治-052",
"noble6": "斯巴达-B312"
}
}
2.数据解析
介绍几个用到的重要函数
CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);
作用:将一个JSON数据包,按照cJSON结构体的结构序列化整个数据包,并在堆中开辟一块内存存储cJSON结构体
返回值:成功返回一个指向内存块中的cJSON的指针,失败返回NULL
cJSON *cJSON_GetObjectItem(cJSON *object,const char *string);
作用:获取JSON字符串字段值
返回值:成功返回一个指向cJSON类型的结构体指针,失败返回NULL
char *cJSON_Print(cJSON *item);
作用:将cJSON数据解析成JSON字符串,并在堆中开辟一块char*的内存空间存储JSON字符串
返回值:成功返回一个char*指针该指针指向位于堆中JSON字符串,失败返回NULL
void cJSON_Delete(cJSON *c);
作用:释放位于堆中cJSON结构体内存
下面是json解析的全部代码
#include <stdio.h>
#include <stdlib.h>
#include "cJSON.h"
#include "test.h"
int cJSON_main(void)
{
cJSON *json,*json_name,*json_passwd,*json_num;//JSON数据包创建
char* out="{\"name\":\"jhon\",\"passwd\":\"123\",\"num\":1}";
//printf("%s\n",out);
json = cJSON_Parse(out); //解析成json形式
if(json==NULL)
{
printf("json pack into cjson error...");//判断cJSON_Parse是否打包成功
}
else
{
cJSON_Print(json);//打包成功调用cJSON_Print打印输出
printf("ok\r\n");
}
json_name = cJSON_GetObjectItem( json , "name" ); //获取键值内容
json_passwd = cJSON_GetObjectItem( json , "passwd" );
json_num = cJSON_GetObjectItem( json , "num" );
printf("name:%s\npasswd:%s\nnum:%d\n",json_name->valuestring,json_passwd->valuestring,json_num->valueint);
cJSON_Delete(json); //释放内存
free(out);
}
输出结果
ok
name:jhon
passwd:123
num:1
下面是cJSON.h函数的解释机翻
/*The cJSON结构 */
typedef struct cJSON
{
/* next / prev允许您遍历数组/对象链。或者,使用GetArraySize
/GetArrayItem / GetObjectItem */
struct cJSON *next;
struct cJSON *prev;
/* 数组或对象项将有一个子指针指向数组/对象中的项链。*/
struct cJSON *child;
/* 项目的类型,如上所述. */
int type;
/* item的字符串,如果type == cJSON_String并且type == cJSON_Raw */
char *valuestring;
/* w入valueint是DEPRECATED,使用cJSON_SetNumberValue代替*/
int valueint;
/* 项目的编号,如果type == cJSON_Number */
double valuedouble;
/* 项目的名称字符串,如果此项目是子项,或者在对象的子项列表中。 */
char *string;
} cJSON;
typedef struct cJSON_Hooks
{
/* malloc / free是Windows上的CDECL,无论编译器的默认调用约定如何,因此请确保挂钩允许直接传递这些函数。*/
void *(CJSON_CDECL *malloc_fn)(size_t sz);
void (CJSON_CDECL *free_fn)(void *ptr);
} cJSON_Hooks;
typedef int cJSON_bool;
/* 限制嵌套数组/对象在cJSON拒绝解析它们之前的深度 *这是为了防止堆栈溢出。*/
#ifndef CJSON_NESTING_LIMIT
#define CJSON_NESTING_LIMIT 1000//最大深度1000
#endif
/* 将cJSON的版本作为字符串返回 */
CJSON_PUBLIC(const char*) cJSON_Version(void);
/* 为cJSON提供malloc,realloc和free函数 */
CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks);
/*内存管理:调用者总是负责释放cJSON_Parse(带有cJSON_Delete)和cJSON_Print(带有stdlib free,cJSON_Hooks.free_fn或cJSON_free)的所有变体的结果。例外是cJSON_PrintPreallocated,调用者对缓冲区负有全部责任。*/
/*提供一个JSON块,这将返回一个可以查询的cJSON对象。*/
CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);
/* ParseWithOpts允许您要求(并检查)JSON是否为空终止,并检索指向解析的最终字节的指针。*/
/*如果在return_parse_end中提供ptr并且解析失败,则return_parse_end将包含指向错误的指针,因此将匹配cJSON_GetErrorPtr()。*/
CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated);
/*将cJSON实体渲染为文本以进行传输/存储。*/
CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item);
/*将cJSON实体渲染为文本以进行传输/存储,无需任何格式。*/
CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item);
/*使用缓冲策略将cJSON实体渲染为文本。预缓冲是对最终尺寸的猜测。猜测很好地减少了重新分配。fmt = 0给出无格式,= 1给出格式化*/
CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt);
/*使用已在内存中分配给定长度的缓冲区将cJSON实体渲染为文本。成功时返回1,失败时返回0。*/
/*注意:cJSON在估计它将使用多少内存时并不总是100%准确,因此安全分配比实际需要多5个字节*/
CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format);
/*删除cJSON实体和所有子实体。*/
CJSON_PUBLIC(void) cJSON_Delete(cJSON *c);
/*返回数组(或对象)中的项数。*/
CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array);
/*从数组“array”中检索项目编号“index”。如果不成功则返回NULL。*/
CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index);
/*从对象获取项目“字符串”。不区分大小写。*/
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string);
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string);
CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string);
/*用于分析失败的解析。这将返回指向解析错误的指针。你可能需要回顾几个字符来理解它。当cJSON_Parse()成功时,cJSON_Parse()返回0时定义。*/
CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void);
/*检查项是否为字符串并返回其valuestring */
CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item);
/*这些函数检查项目的类型*/
CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item);
/*这些调用创建适当类型的cJSON项。*/
CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean);
CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num);
CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string);
/* raw json */
CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw);
CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void);
/*创建一个字符串,其中valuestring引用一个字符串,它不会被cJSON_Delete 释放*/
CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string);
/ *创建一个只引用它的元素的对象/数组它们不会被cJSON_Delete释放 */
CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child);
CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child);
/*这些实用程序创建一个计数项数组。*/
CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count);
/*将项附加到指定的数组/对象。*/
CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item);
CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
/*当string绝对是const(即文字,或者说好)时使用它,并且肯定会在cJSON对象中存活。*警告:使用此功能时,请务必检查(item-> type&cJSON_StringIsConst)为零之前,写入`item-> string` */
CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item);
/*将对项的引用附加到指定的数组/对象。如果要将现有cJSON添加到新的cJSON,但不想破坏现有的cJSON,请使用此选项。*/
CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);
/*从数组/对象中删除/分离项目。*/
CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which);
CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string);
CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string);
CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string);
/*更新数组项。*/
CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /*将预先存在的项目向右移动。*/
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement);
CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
CJSON_PUBLIC(void) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem);
/*复制一个cJSON项目*/
CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse);
/* Duplicate将在你传递的新内存中创建一个新的,相同的cJSON项目需要被释放。使用recurse!= 0,它将复制连接到该项目的所有子项。从Duplicate返回时,item-> next和 - > prev指针始终为零。递归地比较两个cJSON项的相等性。如果a或b为NULL或无效,则它们将被视为不相等。 case_sensitive确定对象键是否区分大小写(1)或不区分大小写(0)*/
CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive);
CJSON_PUBLIC(void) cJSON_Minify(char *json);
/* Helper函数用于同时创建和添加项目到对象。它们返回添加的项目或失败时为NULL。*/
CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean);
CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number);
CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string);
CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw);
CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name);
/*当分配一个整数值时,它也需要传播到有价值的值。*/
#define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number))
/*用于迭代数组或对象的宏*/
CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number);
#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number))
/*cJSON_SetNumberValue宏的助手*/
#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
/* malloc / free对象使用已使用cJSON_InitHooks设置的malloc / free函数*/
CJSON_PUBLIC(void *) cJSON_malloc(size_t size);
CJSON_PUBLIC(void) cJSON_free(void *object);