嵌入式中JSON数据格式实现—cJSON
admin 于 2017年08月31日 发表在 嵌入式开发笔记
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;