Arduino学习笔记:JSON报文的解析与构建
背景:由于最近博主在忙于完成毕业设计,毕业设计用到了MQTT协议去传递消息,在消息的传递过程中呢,采用的是JSON报文的格式,因此在学习的过程中写下此篇建议的Demo,用于给更多萌新或者小白指明道路。
首先我们需要下载Arduino进行JSON解析需要的库文件,博主将库文件直接放到百度网盘中了,需要的可以下载,下载完成后放在自己的libraries库中即可。
链接:https://pan.baidu.com/s/1YvsHvjFvVrmrXI-lW7geJA?pwd=1234
提取码:1234
Arduino解析JSON
本项目中定义的JSON报文格式如下,包含了不仅简单的JSON格式:“Key”:“Value”;还包含了JSON数组和嵌套格式。该报文中的字符串内容可在JSON可视化网站上进行格式化。
JSON可视化网址:JSON可视化网站
{
"NameString": "ZhanSan",
"InfoArray": [
180,
70
],
"Birthday": {
"Year": 2000,
"Mother": 10,
"Day": {
"Hour": 12,
"Min": 45,
"Sec": 32.5
}
}
}
在该网站上能够对自己的JSON报文进行格式化并显示对应关系的视图,来检验层级关系是否正确。
在Arduino中使用的时候需要在该网址中进行删除空格并转义的操作得到如下报文。
我们将该段报文复制下来放在我们的Arduino代码中,得到如下字符串:
String JSON_Value ="{\"NameString\":\"ZhanSan\",\"InfoArray\":[180,70],\"Birthday\":{\"Year\":2000,\"Mother\":10,\"Day\":{\"Hour\":12,\"Min\":45,\"Sec\":32.5}}}";
从这段报文中我们能够看出,有字符串类型的数据,有数组类型的数据,有整型的数据还有浮点型的数据,嵌套层数也能够达到3级,其实只要是大于2级,解析的方式都是一样的,为了方便大家类比,在此我创建了3层。
下面给出源码:
#include <ArduinoJson.h> /* 引入JSON解析需要用的库文件 */
//StaticJsonDocument<1024> doc; /* 声明一个大小为1K的StaticJsonDocument对象doc,用于存储构建的JSON报文,以StaticJsonDocument方式声明的对象将存储在栈内存中,推荐size不大于1K时使用该方式 */
DynamicJsonDocument JSON_Buffer(2*1024); /* 申明一个大小为2K的DynamicJsonDocument对象JSON_Buffer,用于存储反序列化后的(即由字符串转换成JSON格式的)JSON报文,方式声明的对象将存储在堆内存中,推荐size大于1K时使用该方式 */
const char *Name = NULL; /* 用于接收解析后的JSON报文中的NameString的值 */
int InfoOne = 0; /* 用于接收解析后的JSON报文中的InfoArray数组中下表为0的值 */
int InfoTwo = 0; /* 用于接收解析后的JSON报文中的InfoArray数组中下表为1的值 */
int Year = 0; /* 用于接收解析后的JSON报文中的Year的值 */
int Mother = 0; /* 用于接收解析后的JSON报文中的Mother的值 */
int Hour = 0; /* 用于接收解析后的JSON报文中的Hour的值 */
int Min = 0; /* 用于接收解析后的JSON报文中的Min的值 */
float Sec = 0.0; /* 用于接收解析后的JSON报文中的Sec的值 */
JsonObject root; /* 定义一个JSON对象的根节点root 用于获取将JSON字符串经过显示类型转换为JSON对象的报文主体 */
void setup() {
Serial.begin(115200);
/* 首先定义一个JSON 字符串用于解析使用 */
char JSON_Value[] ="{\"NameString\":\"ZhanSan\",\"InfoArray\":[180,70],\"Birthday\":{\"Year\":2000,\"Mother\":10,\"Day\":{\"Hour\":12,\"Min\":45,\"Sec\":32.5}}}";
/* 反序列化转换前,先输出一遍JSON字符串,用于对比反序列化后的报文 */
Serial.println("====================Before================================");
Serial.println(JSON_Value);
DeserializationError error = deserializeJson(JSON_Buffer, JSON_Value); /* 将JSON_Value字符串反序列化为JSON报文的格式,存入JSON_Buffer中 */
if(error)/* 若反序列化返回错误,则打印错误信息,然后中止程序 */
{
Serial.println("deserializeJson JSON_Buffer is ERROR!!!");
return ;
}
else
{
root = JSON_Buffer.as<JsonObject>(); /* 获取将JSON字符串经过显示类型转换为JSON对象的报文主体 */
Serial.println("====================After================================");
serializeJsonPretty(JSON_Buffer, Serial); /* 反序列化成功则,打印格式化后的JSON报文 */
Name = JSON_Buffer["NameString"]; /* 对于获取第一层级的值来说只要解析该值的键名就行 */
InfoOne = JSON_Buffer["InfoArray"][0]; /* 解析数组元素的时候,要先解析该数组的键名,再通过数组下标0解析第一个元素 */
InfoTwo = JSON_Buffer["InfoArray"][1]; /* 解析数组元素的时候,要先解析该数组的键名,再通过数组下标1解析第二个具体元素 */
Year = JSON_Buffer["Birthday"]["Year"]; /* 对于获取第二层级的值来说,只要先解析第一层级的值,再解析第二层级的值就行,表现在代码中就是二维数组 */
Mother = JSON_Buffer["Birthday"]["Mother"];
Hour = JSON_Buffer["Birthday"]["Day"]["Hour"]; /* 对于获取第三层级的值来说,类比第二层级,只要先解析第一层级的值,再解析第二层级的值,最后解析第三层级的值就行,表现在代码中就是三维数组 */
Sec = JSON_Buffer["Birthday"]["Day"]["Sec"]; /* 对于浮点数来说步骤一样 */
/* 所有元素解析完成后我们依次打印出来看看值对不对 */
Serial.println("================Start===========================");
Serial.println(Name);
Serial.println(InfoOne);
Serial.println(InfoTwo);
Serial.println(Year);
Serial.println(Hour);
Serial.println(Sec);
Serial.println("=================END==========================");
}
}
void loop() {
}
运行结果:
Arduino 构建JSON报文
上面我们完成了一个JSON字符串转换为JSON报文的格式再进行解析的过程,下面我们来构建一个完整的JSON报文。
源码部分:
#include <ArduinoJson.h> /* 引入JSON解析需要用的库文件 */
DynamicJsonDocument JSON_Buffer(2*1024); /* 申明一个大小为2K的DynamicJsonDocument对象JSON_Buffer,用于存储反序列化后的(即由字符串转换成JSON格式的)JSON报文,方式声明的对象将存储在堆内存中,推荐size大于1K时使用该方式 */
JsonArray InfoArray; /* 创建一个JSON数组对象 */
JsonObject BirthedayObj; /* 创建一个JSON节点对象,第二层级的主节点 */
JsonObject DayObj; /* 创建一个JSON节点对象,第三层级的主节点 */
void setup() {
Serial.begin(115200);
JSON_Buffer["NameString"] = "ZhangSan"; /* 创建第一层级的一个键名为NameString,值为ZhangSan的属性 */
InfoArray = JSON_Buffer.createNestedArray("InfoArray"); /* 创建一个数组节点 */
InfoArray.add(180); /* 添加数组第一个元素为180*/
InfoArray.add(70); /* 添加数组第二个元素为70*/
JSON_Buffer["InfoArray"][0]; /* 创建完成后将其加入JSON报文中 */
JSON_Buffer["InfoArray"][1];
BirthedayObj = JSON_Buffer.createNestedObject("Birthday"); /* 创建第二层级的主节点,键名为Birthday */
JSON_Buffer["Birthday"]["Year"] = 2000; /* 在第二层级中,创建一个键名为Year,值为2000的属性 */
JSON_Buffer["Birthday"]["Mother"] = 10; /* 在第二层级中,创建一个键名为Mother,值为10的属性 */
JSON_Buffer["Birthday"]["Day"]["Hour"] = 12; /* 在第三层级中,创建一个键名为Hour,值为12的属性,第三层级直接加入第二层级后面就行不需要再额外创建节点,只有和第二层级处于同一层级的需要额外建立节点 */
JSON_Buffer["Birthday"]["Day"]["Min"] = 45; /* 在第三层级中,创建一个键名为Min,值为45的属性 */
JSON_Buffer["Birthday"]["Day"]["Sec"] = 32.5; /* 在第三层级中,创建一个键名为Sec的浮点型数,值为32.5的属性 */
serializeJsonPretty(JSON_Buffer, Serial);
}
void loop() {
}
运行结果: