前言
之前我曾经写过几个JSON解析库的使用方法:
Qt平台下使用QJson解析和构建JSON字符串
使用cJSON库解析JSON
使用cJSON库构建JSON
对于嵌入式开发,比较常用的就是cJSON解析库了,但是使用这个库对内存开销比较大,需要大量使用malloc和free进行动态内存分配和释放。对于单片机这种资源短缺的芯片来说,简直是太吃力了。使用STM32等单片机,不能解析多层JSON时,还需要调大堆栈。
今天来了解一下一个和cJSON非常类似的解析库——Jansson的使用,支持解析和构建JSON字符串,不需要动态分配内存,使用方法和cJSON几乎一样。
本文以Keil环境下的Jansson为例,介绍多种不同格式的JSON字符串解析。
示例工程下载:whik1194-JanssonDemo.rar
Jansson的安装
Jansson的安装非常简单,到Keil官网下载一个Jansson的Pack包即可: Keil.Jansson.1.0.0.pack,点击直接下载。
安装完成之后,如果要在当前项目中添加Jansson解析库,在Keil中勾选上Jansson即可,选择完成之后,在当前工程下会出现两个文件:jansson_CM3LE.lib
和jansson_config.c
。
在要使用的文件中包含头文件:#include
为了方便调试,自定义实现了一个串口格式化输出函数:LOG1。
void LOG1(char *fmt,...)
{unsigned char UsartPrintfBuf[296];va_list ap;unsigned char *pStr = UsartPrintfBuf;va_start(ap, fmt);vsnprintf((char *)UsartPrintfBuf, sizeof(UsartPrintfBuf), fmt, ap); //格式化va_end(ap);while(*pStr != 0){while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);USART_SendData(USART1, *pStr++);}
}
示例1:纯键值对
JSON字符串,包括字符串、整形和布尔类型三种类型的键值对:
{"status": true,"age": 20,"name": "whik1194","blog": "https://blog.csdn.net/whik1194","wechat": "mcu149"
}
解析函数:
uint8_t Jansson1_Demo(void)
{const char *text = "{"status":true,"age":20,"score":78.4,"name":"whik1194","blog":"https://blog.csdn.net/whik1194","wechat":"mcu149"}";json_error_t error;json_t *root;json_t *status;char *name, *blog, *wechat;int age;double score;root = json_loads((const char*)text, 0, &error); if(json_is_object(root)){LOG1("root format correctrn");/* string 类型的解析 */name = (char *)json_string_value(json_object_get(root, "name"));blog = (char *)json_string_value(json_object_get(root, "blog"));wechat = (char *)json_string_value(json_object_get(root, "wechat"));LOG1("name: %srn", name);LOG1("blog: %srn", blog);LOG1("wechat: %srn", wechat);/* int 类型的解析 */age = json_integer_value(json_object_get(root, "age"));LOG1("age: %drn", age);/* double 类型的解析 */score = json_real_value(json_object_get(root, "score"));LOG1("score: %.1frn", score);/* bool 类型的解析 */status = json_object_get(root, "status");if(json_is_true(status))LOG1("status: truern");else if(json_is_false(status))LOG1("status: falsern");}else{printf("root format error:%d-%srn", error.line, error.text);return 1;}return 0;
}
运行结果:
示例2:键的值是一个对象
JSON字符串,其中result键的值是一个JSON对象,包括几组键值对:
{"success": "1","result": {"timestamp": "1592640249","datetime_1": "2020-06-20 16:04:09","week_1": "6","week_2": "Saturday"}
}
解析函数:
uint8_t Jansson2_Demo(void)
{const char *text = "{"success":"1","result":{"timestamp":"1592640249","datetime_1":"2020-06-20 16:04:09","week_1":"6","week_2":"Saturday"}}";json_error_t error;json_t *root;json_t *result;char *success;char *timestamp;char *datetime_1;char *week_1;root = json_loads((const char*)text, 0, &error); if(json_is_object(root)){LOG1("root format correctrn");success = (char *)json_string_value(json_object_get(root, "success"));LOG1("success:%srn", success);result = json_object_get(root, "result");if(json_is_object(result)){timestamp = (char *)json_string_value(json_object_get(result, "timestamp"));datetime_1 = (char *)json_string_value(json_object_get(result, "datetime_1"));week_1 = (char *)json_string_value(json_object_get(result, "week_1"));LOG1("timestamp:%srn", timestamp);LOG1("datetime_1:%srn", datetime_1);LOG1("week_1:%srn", week_1);}else {LOG1("reuslt format errorrn");return 1;}}else{LOG1("root format error:%d-%srn", error.line, error.text);return 1;}return 0;
}
运行结果:
示例3:键的值是一个数组
JSON字符串,键的值是一个JSON数组,包含两个JSON对象:
{"location": [{"name": "Faye","address": "Beijing"}, {"name": "Andy","address": "ShangHai"}, {"name": "Lisa","address": "ShenZhen"}],"time": "2018-11-17"
}
解析函数:
uint8_t Jansson3_Demo(void)
{const char *text = "{"location":[{"name":"Faye","address":"Beijing"},{"name":"Andy","address":"ShangHai"},{"name":"Lisa","address":"ShenZhen"}],"time":"2018-11-17"}";json_error_t error;json_t *root;json_t *location_arr;json_t *location;char *name, *address;char *time;int idx;root = json_loads((const char*)text, 0, &error); if(json_is_object(root)){LOG1("root format correctrn");time = (char *)json_string_value(json_object_get(root, "time"));location_arr = json_object_get(root, "location");if(json_is_array(location_arr)){for(idx = 0; idx }
运行结果:
注意
如果出现解析失败,或者解析错误,可以尝试增加Heap_Size大小:
不知道是不是编码的问题,Jansson并不支持含有中文的JSON字符串解析,会报格式错误。
示例工程下载:whik1194-JanssonDemo.rar