Jansson-STM32
STM32处理json字符串一般不常见,大部分都是不需要处理的数据,但是在一些通信中需要处理上传或者下传的数据,就别比如在物联网中,有一部分数据就是以json格式传输的,那么就需要对数据经行解析。我简单记录一下我自己在STM32F103RC中使用jansson库的一些注意事项和出现的错误
今天来了解一下一个和cJSON非常类似的解析库——Jansson的使用,支持解析和构建JSON字符串,不需要动态分配内存,使用方法和cJSON几乎一样。
1、Json简介
一、JSON:JavaScript Object Notation的简写,是一种轻量级数据交换格式。 二、数据类型:标量、序列(数组)、映射(key-value) 三、JSON的四个原则 1 、并列数据之间用逗号隔开 2、 映射用冒号:来表示 3 、并列数据的集合用中括号[]来表示 4、 映射的集合用大括号{}来表示 如下形式: {"name": "John Doe", "age": 18, "address": { "country" : "china", "zip-code": "10000" } } 四、JSON的优点 1、 数据格式比较简单,格式是压缩的,占用带宽小 2、 支持Python等服务器端语言,便于服务器解析
2、jansson库的下载安装和报错解决
Jansson官网:http://jansson.readthedocs.io/en/latest/
Jansson API文档:http://jansson.readthedocs.io/en/latest/apiref.html
关于Jansson库的更多使用请查看官方文档。
2.1、下载安装
jansson库是有Keil版本的官方的,可以直接在官网下载,官网链接,下载安装就可以使用了,但是还会遇到其它问题。记录一下我自己的问题。
下载下来的文件:
2.2、STM32工程文件中导入jansson库
打开自己的工程文件,我自己使用的是正点原子的工程文件。
按照下面的顺序选择,就能看到第4布那个了,说明库文件已经添加成功。
2.3、报错解决
添加了库函数之后出现如下报错,经过一番查找,终于找到了原因并且解决了。
对于报错,…\OBJ\Jansson_Test.axf: Error: L6915E: Library reports error: __use_no_semihosting was requested, but _ttywrch was referenced。
在usart.c串口通信文件之中添加如下所示代码即可。
添加代码:
//__use_no_semihosting was requested, but _ttywrch was void _ttywrch(int ch) { ch = ch; }
对于报错,…\OBJ\Jansson_Test.axf: Error: L6915E: Library reports error: __use_no_semihosting was requested, but _sys_open was referenced。
勾选Use MicroLIB 。
2.4、修改堆栈空间
修改启动文件里面的堆栈范围,防止在程序运行过程中空间不足出现死机。
3、Json 字符的创建
//jansson Test void jansson_pack_test(void) { json_t *root; // json_t用于引用任何JSON节点 char *out; /* Build an empty JSON object */ root = json_pack("{}"); out = json_dumps(root, JSON_ENCODE_ANY); printf("out:%s\r\n", out); json_delete(root); free(out); /* Build the JSON object {"foo": 42, "bar": 7} */ root = json_pack("{sisi}", "foo", 42, "bar", 7); out = json_dumps(root, JSON_ENCODE_ANY); printf("out:%s\r\n", out); json_delete(root); free(out); /* Like above, ':', ',' and whitespace are ignored */ root = json_pack("{s:i, s:i}", "foo", 42, "bar", 7); out = json_dumps(root, JSON_ENCODE_ANY); printf("out:%s\r\n", out); json_delete(root); free(out); /* Build the JSON array [[1, 2], {"cool": true}] */ root = json_pack("[[i,i],{s:b}]", 1, 2, "cool", 1); out = json_dumps(root, JSON_ENCODE_ANY); printf("out:%s\r\n", out); json_delete(root); free(out); /* Build a string from a non-null terminated buffer */ char buffer[4] = {'t', 'e', 's', 't'}; root = json_pack("[s#]", buffer, 4); out = json_dumps(root, JSON_ENCODE_ANY); printf("out:%s\r\n", out); json_delete(root); free(out); /* Concatenate strings together to build the JSON string "foobarbaz" */ root = json_pack("[s++]", "foo", "bar", "baz"); out = json_dumps(root, JSON_ENCODE_ANY); printf("out:%s\r\n", out); json_delete(root);//不要用free,用free()会导致Heap溢出 //free(root); free(out); }
输出结果;
其中要特别注意到,json_delete()和free()函数的使用,json_delete()函数可以清空json_t格式的内存,json_t格式使用 free()函数是无法清空,但是free()函数可以清空非json_t格式的。如下图所示:
4、Json 字符的解析
4.1 纯键值对
//纯键值对 { "status":true, "age":20, "Score":88.9, "name":"CQS", "blog":"https://blog.csdn.net/weixin_45488643", "wechat":"QingYeMuRong" }
uint8_t Jansson_Key(void) //纯键值对 { const char *text = "{\"status\":true,\"age\":20,\"score\":88.88,\"name\":\"CQS\",\"blog\":\"https://blog.csdn.net/weixin_45488643\",\"wechat\":\"QingYeMuRong\"}"; 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)) // 如果读取失败,自动置为空指针 { /* 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")); printf("name: %s\r\n", name); printf("blog: %s\r\n", blog); printf("wechat: %s\r\n", wechat); /* int 类型的解析 */ age = json_integer_value(json_object_get(root, "age")); printf("age: %d\r\n", age); /* double 类型的解析 */ score = json_real_value(json_object_get(root, "score")); printf("score: %.1f\r\n", score); /* bool 类型的解析 */ status = json_object_get(root, "status"); if(json_is_true(status)) printf("status: true\r\n"); else if(json_is_false(status)) printf("status: false\r\n"); } else { printf("root format error:%d-%s\r\n", error.line, error.text); return 1; } return 0; }
输出结果:
4.2、键的值是一个对象
//键的值是一个对象 { "success": "1", "result": { "timestamp": "12345678900", "datetime_1": "2020-07-04 16:04:09", "week_1": "6", "week_2": "Saturday" } }
uint8_t Jansson_Object(void) //键的值是一个对象 { const char *text = "{\"success\":\"1\",\"result\":{\"timestamp\":\"12345678900\",\"datetime_1\":\"2020-07-04 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)) { printf("root format correct\r\n"); success = (char *)json_string_value(json_object_get(root, "success")); printf("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")); printf("timestamp:%s\r\n", timestamp); printf("datetime_1:%s\r\n", datetime_1); printf("week_1:%s\r\n", week_1); } else { printf("reuslt format error\r\n"); return 1; } } else { printf("root format error:%d-%s\r\n", error.line, error.text); return 1; } return 0; }
输出结果:
4.3、键的值是一个数组
{ "location": [{ "name": "Faye", "address": "Tianjing" }, { "name": "Andy", "address": "XinJiab" }, { "name": "Lisa", "address": "WuLu" }], "time": "2020-07-04" }
```c uint8_t Jansson_Array (void) //键的值是一个数组 { const char *text = "{\"location\":[{\"name\":\"Faye\",\"address\":\"Beijing\"},{\"name\":\"Andy\",\"address\":\"ShangHai\"},{\"name\":\"Lisa\",\"address\":\"ShenZhen\"}],\"time\":\"2020-07-04\"}"; 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)) { printf("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")); printf("%d: %s-%s\r\n", idx, name, address); } } } else { printf("root format error:%d-%s\r\n", error.line, error.text); return 1; } return 0; }