2. JSON基础概念:JSON数据结构、键值对、数组与对象、JSON与XML对比
好,咱们正式开始聊JSON。说实话,我在嵌入式这行摸爬滚打十几年,JSON是我见过最「实在」的数据格式之一。你想想看,在ESP32这种资源受限的芯片上,要搞数据交换,JSON几乎是绕不开的选择。今天我就把它的底裤扒干净,从最基础的结构讲起。
2.1 什么是JSON?
JSON,全称JavaScript Object Notation,直译过来就是「JavaScript对象表示法」。但别被名字骗了——它跟JavaScript语言本身没半毛钱关系。它只是一种轻量级的数据交换格式。
我个人习惯把JSON看作「数据的快递箱」。你往里面塞东西,贴上标签,然后扔到网络上。另一端收到后,拆开箱子,按标签取出数据。就这么简单。
核心要点:JSON的本质是文本,不是二进制。它用纯文本的方式描述结构化数据。这意味着任何能处理字符串的设备都能解析JSON——包括你那块小小的ESP32。
2.2 JSON的数据结构
JSON只有两种顶层结构,记住这两个就够了:
- 对象(Object):用花括号
{}包裹,里面是一堆键值对 - 数组(Array):用方括号
[]包裹,里面是一堆值
嗯,这里要注意:这两种结构可以无限嵌套。对象里套数组,数组里套对象,对象里再套对象……只要你内存够,随便套。
2.2.1 键值对(Key-Value Pair)
这是JSON最基本的组成单元。格式很简单:
"key" : value
左边是键,必须是双引号包裹的字符串。右边是值,可以是以下几种类型:
| 类型 | 示例 | 说明 |
|---|---|---|
| 字符串 | "hello" | 必须用双引号 |
| 数字 | 42 或 3.14 | 整数或浮点数,不用引号 |
| 布尔值 | true 或 false | 小写,不用引号 |
| 空值 | null | 表示空,不是字符串"null" |
| 对象 | {...} | 嵌套的子对象 |
| 数组 | [...] | 有序的值列表 |
我在项目中遇到过最坑的事:有人把数字用引号包起来当字符串传,结果接收端做数学运算时直接崩了。记住,数字就是数字,别加引号。
2.2.2 对象(Object)
对象就是一组键值对的集合。看个例子:
{
"name": "ESP32温度传感器",
"temperature": 26.5,
"unit": "°C",
"online": true
}
这个对象描述了某个温度传感器的状态。它有4个键值对,分别表示名称、温度值、单位和在线状态。
小技巧:键名最好用驼峰命名法(如 sensorName)或下划线命名法(如 sensor_name)。我个人习惯用下划线,因为在C语言里处理起来更顺手。但无论选哪种,整个项目要保持一致。
2.2.3 数组(Array)
数组就是有序的值列表。每个元素可以是任意类型,包括对象或其他数组:
{
"sensors": [
{"id": 1, "temp": 25.3},
{"id": 2, "temp": 26.1},
{"id": 3, "temp": 24.8}
]
}
这个例子中,sensors 键对应的值是一个数组,里面包含了3个传感器对象。每个对象又有自己的 id 和 temp 字段。
为什么会这样设计?因为实际场景中,你往往需要批量上报数据。比如ESP32接了3个DS18B20温度探头,用数组一次性打包发送,比发3次单独请求高效得多。
2.3 JSON与XML对比
说到数据交换格式,就绕不开XML。XML比JSON老得多,90年代末就出来了。我刚开始做嵌入式时,用的全是XML。后来JSON逐渐普及,现在基本成了事实标准。
咱们直接上对比表:
| 对比项 | JSON | XML |
|---|---|---|
| 语法复杂度 | 简单,只有几种结构 | 复杂,有标签、属性、命名空间等 |
| 数据体积 | 小,没有冗余标签 | 大,每个数据都要开闭标签 |
| 解析速度 | 快,结构简单 | 慢,需要解析DOM树 |
| 可读性 | 好,结构清晰 | 一般,标签多了眼花 |
| 元数据支持 | 弱,没有属性概念 | 强,支持标签属性 |
| 嵌入式适用性 | 非常适合 | 不太适合,太占资源 |
拿同一个数据来对比,你感受一下:
JSON版本:
{
"device": "ESP32",
"firmware": "v2.1.0",
"sensors": [
{"type": "temperature", "value": 25.3},
{"type": "humidity", "value": 60.5}
]
}
XML版本:
<device name="ESP32" firmware="v2.1.0">
<sensors>
<sensor type="temperature">25.3</sensor>
<sensor type="humidity">60.5</sensor>
</sensors>
</device>
你看,同样的数据,XML多了多少字符?在ESP32这种只有几百KB RAM的芯片上,每多一个字节都是负担。
避坑指南:我曾经在一个项目里坚持用XML做设备间通信,结果ESP32解析一个200KB的XML文件,直接内存溢出重启了。后来换成JSON,同样的数据只有80KB,解析速度还快了3倍。从那以后,我在嵌入式领域再也没用过XML做数据传输。
2.4 什么时候该用JSON?什么时候不该用?
说白了,JSON不是万能的。我总结了几条经验:
- 适合用JSON的场景:设备状态上报、传感器数据采集、配置文件的读写、API接口通信
- 不适合用JSON的场景:需要严格数据验证(用XML Schema)、传输二进制文件(用Base64编码太浪费)、对性能要求极高(考虑用Protocol Buffers或MessagePack)
嗯,这里要补充一句:在ESP32上,JSON解析库有很多选择。我个人最常用的是 cJSON,轻量、稳定、API设计得也很顺手。后面章节我会专门讲怎么在ESP32上玩转cJSON。
2.5 小结
今天咱们把JSON的底子打牢了。你记住了吗?
- JSON只有对象和数组两种结构
- 键值对是基本单元,键必须加双引号
- 值有6种类型:字符串、数字、布尔、null、对象、数组
- JSON比XML更适合嵌入式场景——体积小、解析快、实现简单
下一章,咱们就动手在ESP32上写代码,用cJSON库来封装和解析JSON数据。到时候你会发现,这些基础概念会变得特别实在。