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"必须用双引号
数字423.14整数或浮点数,不用引号
布尔值truefalse小写,不用引号
空值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个传感器对象。每个对象又有自己的 idtemp 字段。

为什么会这样设计?因为实际场景中,你往往需要批量上报数据。比如ESP32接了3个DS18B20温度探头,用数组一次性打包发送,比发3次单独请求高效得多。

2.3 JSON与XML对比

说到数据交换格式,就绕不开XML。XML比JSON老得多,90年代末就出来了。我刚开始做嵌入式时,用的全是XML。后来JSON逐渐普及,现在基本成了事实标准。

咱们直接上对比表:

对比项JSONXML
语法复杂度简单,只有几种结构复杂,有标签、属性、命名空间等
数据体积小,没有冗余标签大,每个数据都要开闭标签
解析速度快,结构简单慢,需要解析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数据。到时候你会发现,这些基础概念会变得特别实在。