下载库并进行安装

首先去官网下载Keil.Jansson.1.0.0.pack
[[https://keilpack.azureedge.net/pack/Keil.Jansson.1.0.0.pack]]
下载后双击打开,安装到本地的keil5中,打开查看是否安装成功
在这里插入图片描述

jansson库优点

  • 轻量级:代码量较小,适合资源受限的嵌入式系统(如 STM32)。
  • 符合标准:严格遵循 JSON 标准(RFC 8259),支持 UTF-8 编码。
  • 易用性:提供简洁的 API,支持 JSON 对象、数组、字符串、数值等数据类型的操作。
  • 内存安全:自动管理内存分配和释放(但需注意嵌入式环境下的内存限制)。
  • 跨平台:可移植到多种平台,包括 ARM Cortex-M 系列(如 STM32)。

配置jansson库

打开keil5的库管理,在Data Exchange中找到JSON,点击加号打开,找到Jansson,打勾,点击OK
在这里插入图片描述

在工程中如果发现下图,即代表配置成功
在这里插入图片描述

使用实例1-生成json格式数据

如果需要生成固定格式的json数据,使用snprintf即可,例如生成

{
	"id":"a123",
	"vaule":23
}

可以直接编写代码

char jsonbox[128];
snprintf(jsonbox,128,"{\"id\":\"%s\",\"value\": \"%d\"}","a123",23);
printf("%s\r\n",jsonbox);

编译后下载程序,观察串口助手输出
在这里插入图片描述

也可以将他上传到服务器中进行检验
在这里插入图片描述

也是可以被解析出
当然我们可以使用json库进行生成,还是生成同样结构的数据,代码如下

json_t *jsonbox = json_object();
json_object_set_new(jsonbox, "id", json_string("a123"));
json_object_set_new(jsonbox,"vaule",json_integer(23));
char* json_str = json_dumps(jsonbox, JSON_COMPACT);  //printf无法直接打印json数据
printf("%s\r\n", json_str);

串口输出和服务器输出如下
在这里插入图片描述
在这里插入图片描述


那如果创建复杂的多重嵌套的数据格式呢?比如创建如下

{  
  "id": "a123",  
  "params": {  
    "model": {  
      "value": "deepseek"  
    },  
    "age": {  
      "value": 10  
    }
  }  
}

可以进行如下操作,分别创建对象,添加对应的值后,再将各个对象汇总在一个根对象下,代码如下

json_t *jsonbox = json_object();//创建根对象
json_object_set_new(jsonbox, "id", json_string("a123"));
json_t *jsonparams = json_object();//创建params对象
json_object_set_new(jsonparams,"model",json_string("deepseek"));
json_object_set_new(jsonparams,"age",json_integer(10));
json_object_set_new(jsonbox, "params", jsonparams);  //将对象添加到其中
char* json_str = json_dumps(jsonbox, JSON_INDENT(0));  //printf无法直接打印json数据
printf("%s\r\n", json_str);
json_decref(jsonbox);

输出如下
在这里插入图片描述
在这里插入图片描述

介绍一下json转char格式的flag
格式控制类
主要用于调整 JSON 字符串的排版形式

标志 作用 示例值及效果
JSON_MAX_INDENT (0x1F) 缩进空格数的最大值(强制 JSON_INDENT(n) 中的 n 范围不超过31) -
JSON_INDENT(n) 设置缩进空格数(推荐值为 0-4) JSON_INDENT(4){\n "key": "value"\n}
JSON_COMPACT (0x20) 紧凑模式:消除所有非必要空格和换行 {"id":"a123","value":23}

字符转义类
控制特殊字符的转义规则,确保 JSON 合法性或兼容性。

标志 作用 示例及说明
JSON_ENSURE_ASCII (0x40) 强制 ASCII 转义:非 ASCII 字符转换为 \uXXXX 形式 “中文” → "\u4e2d\u6587"
JSON_ESCAPE_SLASH (0x400) 转义斜杠 /\/(默认不转义) "path": "a/b""path":"a\/b"

数据类型/编码控制
调整 JSON 元素的编码行为或数据精度。

标志 作用 注意事项
JSON_ENCODE_ANY (0x200) 允许编码任意类型(包括未包装的 JSON 对象,慎用可能破坏格式) 处理非标准类型时需谨慎(可能生成无效 JSON)
JSON_REAL_PRECISION(n) 设置浮点数精度(保留 n 位小数,范围 0-31) JSON_REAL_PRECISION(3)3.142(圆周率保留3位)

键顺序控制
调整 JSON 对象键(Key)的输出顺序。

标志 作用
JSON_SORT_KEYS (0x80) 按键名字母升序排列(默认顺序不可预测或按插入顺序)
JSON_PRESERVE_ORDER (0x100) 保留键的插入顺序(默认可能不保证顺序,需依据具体 Jansson 版本)

使用实例2-解析json格式数据

实现了创建json数据,下一步就是解析从服务器等收到的json格式的数据,还是以简单的数据格式为例


{
	"id":"a123",
	"value":23
}

首先创建char格式的数组,调用son_object_get进行提取,但需要注意的是,提取出的数据需要json_string_value进行转换

const char *json_str = "{\"id\":\"a123\",\"value\":23}";
	char id[10];
	char value[10];
	json_t *jsonbox; 
	json_error_t error;
	jsonbox = json_loads(json_str, 0, &error);  
	json_t *id_obj = json_object_get(jsonbox, "id");
	const char *id_val = json_string_value(id_obj);
	snprintf(id, sizeof(id), "%s", id_val);
	
	json_t *value_obj = json_object_get(jsonbox, "value");
	int value_1 = json_integer_value(value_obj);
    snprintf(value, sizeof(value), "%d", value_1);
	printf("id: %s\r\n", id);
    printf("value: %s\r\n", value);

输出结果如下:
在这里插入图片描述

对于接收服务器的数据,首先需要将接收到的数据复制保存,然后进行读取,在回调函数中加入以下代码,即可实现

static void 
mqtt_incoming_data_cb(void *arg, const u8_t *data, u16_t len, u8_t flags)
{
	char *jsonbox = (char *)malloc(len + 1);
    
    if (jsonbox == NULL) {
        printf("内存分配失败!\n");
        return;
    }	
	memcpy(jsonbox, data, len);
    jsonbox[len] = '\0';
    printf("JSON: %s\n", jsonbox); 
	char id[10];
	char value[10];
	json_t *json_val; 
	json_error_t error;
	json_val = json_loads(jsonbox, 0, &error);  
	json_t *id_obj = json_object_get(json_val, "id");
	const char *id_val = json_string_value(id_obj);
	snprintf(id, sizeof(id), "%s", id_val);
	
	json_t *value_obj = json_object_get(json_val, "value");
	int value_1 = json_integer_value(value_obj);
    snprintf(value, sizeof(value), "%d", value_1);
	printf("id_out: %s\r\n", id);
    printf("value_out: %s\r\n", value);
	free(jsonbox);
	
}

编译通过后下载观察效果
在这里插入图片描述

可以看到数据丢失了,因为我们给的数组内存太小了,改大点就OK了
在这里插入图片描述


对于嵌套的数据,一样的操作逻辑,比如传入数据为

{

  "id": "qaduhu37246",

  "value": {

    "age":374732

  }

}

只需要增加一条代码即可

static void 
mqtt_incoming_data_cb(void *arg, const u8_t *data, u16_t len, u8_t flags)
{
	char *jsonbox = (char *)malloc(len + 1);
    
    if (jsonbox == NULL) {
        printf("内存分配失败!\n");
        return;
    }
	memcpy(jsonbox, data, len);
    jsonbox[len] = '\0';
    printf("JSON: %s\n", jsonbox); 
	char id[20];
	char age[10];
	json_t *json_val; 
	json_error_t error;
	json_val = json_loads(jsonbox, 0, &error);  
	json_t *id_obj = json_object_get(json_val, "id");
	const char *id_val = json_string_value(id_obj);
	snprintf(id, sizeof(id), "%s", id_val);
	
	json_t *value_obj = json_object_get(json_val, "value");
	json_t *age_obj = json_object_get(value_obj, "age");//新增代码
	int value_1 = json_integer_value(age_obj);
    snprintf(age, sizeof(age), "%d", value_1);
	printf("id_out: %s\r\n", id);
    printf("value_out: %s\r\n", age);
	free(jsonbox);
	
}

编译后下载检测,成功
在这里插入图片描述

总结

这个库使用还是比较简单的,没有什么困难的地方,json作为传输数据使用还是很方便的。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐