![1a123c967dbaf5214cc4a804213ae6de.png](https://i-blog.csdnimg.cn/blog_migrate/bc17523b18ec8a189a868d5b328f5eb0.jpeg)
ReleaseNote:
2018/12/31 首次发布。
2019/05/07 整理排版,增加几个JSON解析的例子(北京时间、心知天气、和风天气)。
2019/08/19 增加疑问与解答板块。
引言
JSON在上层应用比较多。像最近做的一个WiFi气象站,与气象服务器之间交互后回传的数据便是JSON格式的数据。所以打算写一篇介绍JSON的文章。通过阅读本文,您可以了解到JSON的基本知识,以及在ESP8266上使用cJSON库来生成和解析JSON数据。
- 什么是JSON?
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。采用完全独立于编程语言的文本格式来存储和表示数据。其简洁和层次结构清晰的特点使得 JSON 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。
JSON建构于两种结构:
- “名称/值”对的集合(A collection of name/value pairs)。即常说的Key/Value 键/值对。不同的语言中,它被理解为对象(object),纪录(record),结构(struct),字典(dictionary),哈希表(hash table),有键列表(keyed list),或者关联数组 (associative array)。
- 值的有序列表(An ordered list of values)。在大部分语言中,它被理解为数组(array)。
2. JSON的数据格式
JSON具有以下这些形式:
对象是一个无序的“‘名称/值’对”集合。一个对象以“{”(左括号)开始,“}”(右括号)结束。每个“名称”后跟一个“:”(冒号);“‘名称/值’ 对”之间使用“,”(逗号)分隔。
![a867d080190d52a7a26fc8cfd961453c.png](https://i-blog.csdnimg.cn/blog_migrate/4f8256347e0766e7a89bfe90a399d82f.png)
JSON是键/值对组合,键名写在前面并用双引号 "" 包裹,使用冒号 : 分隔,然后紧接着值。例如:
{"City":"Shenzhen"}
复杂一点:
{"Country":"China","City":"Shenzhen"}
{"Country":"China","City":"Shenzhen","date":"2019-05-07","time":"15:58","temperature":24.6}
数组是值(value)的有序集合。一个数组以“[”(左中括号)开始,“]”(右中括号)结束。值之间使用“,”(逗号)分隔。
![86be4045ade0a4c4f32090791f866a34.png](https://i-blog.csdnimg.cn/blog_migrate/3803803c17f11e945af653736607c48f.png)
例如:
["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
再如:
[[0, -1, 0], [1, 0, 0], [0, 0, 1]]
再如:
{ "IDs": [116, 943, 234, 38793]}
再如:
{"dns":["114.114.114.114","8.8.8.8"]}
再如:
{
"title": "粤港澳大湾区",
"cities": {
"name": ["香港", "澳门", "广州", "深圳", "珠海", "佛山", "惠州", "东莞", "中山", "江门", "肇庆"]
}
}
值(value)可以是双引号括起来的字符串(string)、数值(number)、true
、false
、null
、对象(object)或者数组(array)。这些结构可以嵌套。
![03660ef87689901d974fad89f433da75.png](https://i-blog.csdnimg.cn/blog_migrate/d297a4ef2feb197f0210d0d53a27a84e.png)
{
"result": 1,
"id": 1795565,
"name": "QingQing",
"coord": {
"lon": 114.0545,
"lat": 22.5446
},
"cities": ["Chongqing", "Wuhan", "Nanjing"],
"extra": ""
}
字符串(string)与C或者Java的字符串非常相似,是由双引号包围的任意数量Unicode字符的集合。例如 "Sunshine"。 一个字符(character)即一个单独的字符串(character string)。例如"X"。
![a35d9457e156276aee5be30310c73979.png](https://i-blog.csdnimg.cn/blog_migrate/f420466a374adb2791f4a6ef45531a70.png)
数值(number)也与C或者Java的数值非常相似。除去未曾使用的八进制与十六进制格式。除去一些编码细节。
![1014a17b54eef42894a9f6bde5656ea9.png](https://i-blog.csdnimg.cn/blog_migrate/a9b76ff70d19953df8a110535d692540.png)
例如:{"pi":3.1415926}、{"true":1}、{"false":0}
由上面的几个例子可以看出:JSON 值可以是:
数字(整数或浮点数)
字符串(在双引号中)
逻辑值(true 或 false即1或0)
数组(在方括号中[])
对象(在花括号中{})
null
3. cJSON是什么?
在很多场合中,应用层软件一般使用JSON来传输信息。如果底层的MCU等如果要与应用层通信,就需要进行JSON格式的构造和解析。
cJSON是使用C语言编写的Json格式的解析库,可以运行在许多支持C语言的微处理器上。cJSON其主要功能无非就是构建和解析Json格式了,用途就是一端将要发送的数据以cjson形式封装,然后发送,另一端收到此数据后,还是按cjson形式解析,就得到想要的数据了。
4. JSON实例:
例子1:
{
"colour": {
"red": 100,
"green": 20,
"blue": 235
},
"environment": {
"temperature": 15.8,
"humidity": 50.2
}
}
表示这里分别有两个对象(对象是用{}区分),对象分别是colour、environment。
对于对象colour来说,有3个字段 red、green 和 blue,它们的值类型是int型,值分别是100、20和235;
对于对象environment来说,有2个字段:temperature,它的值类型是float型,值是15.8。humidity,它的值类型是float型,值是50.2。
再加深一遍印象,由上文可以看出JSON其实就相当于 key:value形式的各种组合变化。
JSON数组例子2:
{
"employees": [{
"firstName": "Elon",
"lastName": "Musk"
},
{
"firstName": "Donald",
"lastName": "Trump"
},
{
"firstName": "Thomas",
"lastName": "Carter"
}
]
}
表示这里有一个对象数组(数组用[]区分)employees。
每个对象里面有两个字段firstName和lastName,它们的值类型都是string。
5. 如何生成一个Json字符串?
创建json数据串。这数据串,可能是对象,也可能是数组,也可能是它们的各种组合,其中再加上一些键值对。有一点要先说明:它们的组合,符合父子继承格式--这也是json数据串的特点。
构造 json比较简单,添加json对象即可。参照例子一看大概就明白了。主要就是用cJSON_AddItemToObject函数添加json节点。
比如,我们需要生成如下Json字符串:
{
"semantic": {
"slots": {
"name": "Charlin"
}
},
"rc": 0,
"operation": "CALL",
"service": "telephone",
"text": "打电话给Charlin"
}
代码实现:
#include <stdio.h>
#include "cJSON.h" //包含头文件
int main()
{
cJSON * root = cJSON_CreateObject();
cJSON * item = cJSON_CreateObject();
cJSON * next = cJSON_CreateObject();
cJSON_AddItemToObject(root, "rc", cJSON_CreateNumber(0));//根节点下添加
cJSON_AddItemToObject(root, "operation", cJSON_CreateString("CALL"));
cJSON_AddItemToObject(root, "service", cJSON_CreateString("telephone"));
cJSON_AddItemToObject(root, "text", cJSON_CreateString("打电话给Charlin"));
cJSON_AddItemToObject(root, "semantic", item);//root节点下添加semantic节点
cJSON_AddItemToObject(item, "slots", next);//semantic节点下添加item节点
cJSON_AddItemToObject(next, "name", cJSON_CreateString("Charlin"));//添加name节点
//printf("%sn", cJSON_Print(root));//说明:此用法将造成内存泄漏Memory Leak 正确用法如下:
char* js_str=cJSON_Print(root);//先指向一个指针
printf("%srn",js_str);
if(root)
cJSON_Delete(root); // 释放内存
if(js_str)
free(js_str);//释放内存
return 0;
}
![b133949728bafab5d636f143338db19e.png](https://i-blog.csdnimg.cn/blog_migrate/15796cd42e15bca208d607c2e9f93893.png)