嵌入式中JSON数据格式实现—cJSON
admin 于 2017年09月02日 发表在 嵌入式开发笔记
1. JSON实现语言
访问JSON官网可看到基于众多不同编程语言的JSON解析实现方法,如下:
2. cJSON源码下载
上一篇介绍了《嵌入式中JSON数据格式实现—JSMN》,这一篇介绍另一个流行的C语言JSON解析包—cJSON。
由于官方cJSON更新频繁,所下载的版本可能与本例程不同,因此提供例程源码点击下载附件。
查看下载的文件,核心就两个文件(C语言通用做法):cJSON.c 和 cJSON.h;其中,接口函数的含义都非常明确,可以说是顾名思义了,对于开发者来说很方便。
3. cJSON接口函数
/* The cJSON structure: */
typedef struct cJSON {
struct cJSON *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
int type; /* The type of the item, as above. */
char *valuestring; /* The item's string, if type==cJSON_String */
int valueint; /* The item's number, if type==cJSON_Number */
double valuedouble; /* The item's number, if type==cJSON_Number */
char *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
} cJSON;
typedef struct cJSON_Hooks {
void *(*malloc_fn)(size_t sz);
void (*free_fn)(void *ptr);
} cJSON_Hooks;
/* Supply malloc, realloc and free functions to cJSON */
extern void cJSON_InitHooks(cJSON_Hooks* hooks);
/* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */
extern cJSON *cJSON_Parse(const char *value);
/* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */
extern char *cJSON_Print(cJSON *item);
/* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */
extern char *cJSON_PrintUnformatted(cJSON *item);
/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */
extern char *cJSON_PrintBuffered(cJSON *item,int prebuffer,int fmt);
/* Delete a cJSON entity and all subentities. */
extern void cJSON_Delete(cJSON *c);
/* Returns the number of items in an array (or object). */
extern int cJSON_GetArraySize(cJSON *array);
/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */
extern cJSON *cJSON_GetArrayItem(cJSON *array,int item);
/* Get item "string" from object. Case insensitive. */
extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string);4. cJSON创建对象步骤
//1.创建类型
cJSON *root,*fmt;
char *out;
//2.对象实例(注:fmt双层嵌套)
root=cJSON_CreateObject();
//3.添加对应内容
cJSON_AddItemToObject(root, "name", cJSON_CreateString("Jack (\"Bee\") Nimble")); //add object
cJSON_AddItemToObject(root, "format", fmt=cJSON_CreateObject()); //创建json格式对象fmt
cJSON_AddStringToObject(fmt,"type", "rect"); //添加string类型内容到fmt对象
cJSON_AddNumberToObject(fmt,"width", 1920); //添加int类型内容到fmt对象
cJSON_AddFalseToObject (fmt,"interlace"); //添加bool类型内容到fmt对象
//4.cJSON_Print -> 输出标准化后的格式:{...}
out=cJSON_Print(root);
//out=cJSON_PrintUnformatted -> 输出非格式化的数据,多用于存储和传输
//5.清除实体,释放内存占用
cJSON_Delete(root);
cJSON_Delete(fmt);
free(out);输出结果:
5. cJSON解析字符串步骤
//1.原始JSON格式的字符串
char text[]="{\n\"name\": \"Jack (\\\"Bee\\\") Nimble\", \n\"format\": {\"type\": \"rect\", \n\"width\": 1920, \n\"height\": 1080, \n\"interlace\": false,\"frame rate\": 24\n}\n}";
//2.创建JSON对象
cJSON *json,*result;
//3.解析完字符串并返回JSON实体;
//注:实际应用中,若无法确定字符串text的正确性,则需判断json返回值。
json = cJSON_Parse(text);
//4.从JSON实体中对象获取特定名称的目标
result = cJSON_GetObjectItem(json,"name");
//5.打印对应的值,类型为String、int、float等
printf("%s\n",result->valuestring);
//6.备注:如果需要访问双层嵌套数据
result = cJSON_GetObjectItem(json,"format"); //下一层新的JSON对象
result = cJSON_GetObjectItem(result,"type"); //format对象中目标type
printf("%s\n",result->valuestring); //输出type对应信息
//7.清除内存占用
cJSON_Delete(json);输出结果:
Jack ("Bee") Nimble
6. 通用单片机移植cJSON
以上内容已使用GCC标准C库编译测试,若需移植到不含系统的嵌入式设备(如:STM32单片机),只要替换cJSON.c中的内存管理函数malloc和free即可(如:原子STM32教程中的myfree(),*mymalloc()函数)。
更改后内容如下:
static void *(*cJSON_malloc)(size_t sz) = mymalloc; static void (*cJSON_free)(void *ptr) = myfree;
