文章目录
- 前言
- Jansson的安装
- 示例1:纯键值对
- 示例2:键的值是一个对象
- 示例3:键的值是一个数组
- 注意
前言
之前我曾经写过几个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即可,选择完成之后,在当前工程下会出现两个文件:
在要使用的文件中包含头文件:
为了方便调试,自定义实现了一个串口格式化输出函数:LOG1。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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字符串,包括字符串、整形和布尔类型三种类型的键值对:
1 2 3 4 5 6 7 | { "status": true, "age": 20, "name": "whik1194", "blog": "https://blog.csdn.net/whik1194", "wechat": "mcu149" } |
解析函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | 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 correct\r\n"); /* 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: %s\r\n", name); LOG1("blog: %s\r\n", blog); LOG1("wechat: %s\r\n", wechat); /* int 类型的解析 */ age = json_integer_value(json_object_get(root, "age")); LOG1("age: %d\r\n", age); /* double 类型的解析 */ score = json_real_value(json_object_get(root, "score")); LOG1("score: %.1f\r\n", score); /* bool 类型的解析 */ status = json_object_get(root, "status"); if(json_is_true(status)) LOG1("status: true\r\n"); else if(json_is_true(status)) LOG1("status: true\r\n"); } else { printf("root format error:%d-%s\r\n", error.line, error.text); return 1; } return 0; } |
运行结果:

示例2:键的值是一个对象
JSON字符串,其中result键的值是一个JSON对象,包括几组键值对:
1 2 3 4 5 6 7 8 9 | { "success": "1", "result": { "timestamp": "1592640249", "datetime_1": "2020-06-20 16:04:09", "week_1": "6", "week_2": "Saturday" } } |
解析函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | 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 correct\r\n"); success = (char *)json_string_value(json_object_get(root, "success")); LOG1("success:%s\r\n", 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:%s\r\n", timestamp); LOG1("datetime_1:%s\r\n", datetime_1); LOG1("week_1:%s\r\n", week_1); } else { LOG1("reuslt format error\r\n"); return 1; } } else { LOG1("root format error:%d-%s\r\n", error.line, error.text); return 1; } return 0; } |
运行结果:

示例3:键的值是一个数组
JSON字符串,键的值是一个JSON数组,包含两个JSON对象:
1 2 3 4 5 6 7 8 9 10 11 12 13 | { "location": [{ "name": "Faye", "address": "Beijing" }, { "name": "Andy", "address": "ShangHai" }, { "name": "Lisa", "address": "ShenZhen" }], "time": "2018-11-17" } |
解析函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | 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 correct\r\n"); 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 < json_array_size(location_arr); idx++) { location = json_array_get(location_arr, idx); name = (char *)json_string_value(json_object_get(location, "name")); address = (char *)json_string_value(json_object_get(location, "address")); LOG1("%d: %s-%s\r\n", idx, name, address); } } } else { LOG1("root format error:%d-%s\r\n", error.line, error.text); return 1; } return 0; } |
运行结果:

注意
如果出现解析失败,或者解析错误,可以尝试增加Heap_Size大小:

不知道是不是编码的问题,Jansson并不支持含有中文的JSON字符串解析,会报格式错误。
示例工程下载:whik1194-JanssonDemo.rar