JSON格式介绍 ============== 想象一下,您需要把一段信息从一台电脑传递给另一台电脑,或者从一个程序传递给另一个程序。您需要一种双方都能理解的“通用语言”来写这份信息。JSON(JavaScript Object Notation)就是这种“通用语言”之一,而且可能是目前最受欢迎的一种。 JSON的故事其实很简单:它长得像JavaScript里的对象写法,但它是独立于任何编程语言的。就像全世界很多机场都用英语做指示一样,很多软件系统都用JSON来交换数据。 为什么叫“对象表示法”? ------------------------ 要理解JSON,先得理解“对象”这个概念。在编程世界里,“对象”就像一张信息卡片,或者一个抽屉。 **一个真实的例子**:想象一张“联系人卡片”: :: - 姓名:张三 - 电话:13800138000 - 城市:北京 - 已婚:是 这张卡片有“属性名”(姓名、电话等)和对应的“值”(张三、13800138000等)。在JSON里,这种“属性名-值”的组合就是最基本的单元。 JSON的核心:用文本表示结构化的数据 ----------------------------------- JSON的核心思想是:**用纯文本的方式,来表示有结构的数据**。这种结构主要就是两种:**对象**和**数组**。 对象(Object)—— “带标签的抽屉柜” ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 对象在JSON中用大括号 `{}` 表示。可以把它想象成一个带标签的抽屉柜: - 每个抽屉都有一个**独一无二的标签**(属性名,必须是字符串) - 每个抽屉里放着对应的**东西**(值,可以是各种类型) **JSON写法示例:** .. code-block:: json { "姓名": "张三", "电话": "13800138000", "年龄": 30, "已婚": true } **重要规则:** - 属性名**必须用双引号**包起来(单引号不行!) - 属性名和值之间用冒号 `:` 分隔 - 每个属性之间用逗号 `,` 分隔(最后一个属性后面不要加逗号) 数组(Array)—— “有序的盒子序列” ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 数组在JSON中用中括号 `[]` 表示。可以把它想象成一排编号的盒子: - 盒子有固定的顺序(第一个、第二个、第三个...) - 每个盒子可以放任意类型的东西 - 盒子没有单独的标签,只有位置编号(索引) **JSON写法示例:** .. code-block:: json ["苹果", "香蕉", "橙子", "葡萄"] 数组也可以包含复杂的数据,比如对象: .. code-block:: json [ {"水果": "苹果", "价格": 5.8}, {"水果": "香蕉", "价格": 3.2}, {"水果": "橙子", "价格": 4.5} ] JSON支持的数据类型 ^^^^^^^^^^^^^^^^^^^^^^^^^^ JSON只能表示有限的几种数据类型,但这几种类型已经足够应对大多数情况: 1. **字符串(String)** :用双引号包起来的文本 - 示例:`"Hello, World!"`、`"姓名"`、`"123"`(注意:这里的123是文本,不是数字!) 2. **数字(Number)** :整数或小数,**不用**引号 - 示例:`42`、`3.14`、`-10`、`1.5e3`(科学计数法,表示1500) 3. **布尔值(Boolean)** :表示真或假 - 只有两个值:`true`(真)或 `false`(假) - 示例:`"已婚": true` 4. **空值(Null)** :表示“没有值” - 只有一个值:`null` - 示例:`"中间名": null`(表示没有中间名) 5. **对象(Object)** :前面介绍过,用 `{}` 表示 6. **数组(Array)** :前面介绍过,用 `[]` 表示 **数据类型的重要性** : JSON中的数据类型非常重要,因为接收数据的程序需要知道如何正确处理这些值。比如,数字可以进行数学计算,字符串只能进行文本处理。 一个完整的JSON示例 -------------------- 让我们看一个稍微复杂一点的例子,结合了对象、数组和各种数据类型: .. code-block:: json { "公司": "ABC科技有限公司", "成立年份": 2010, "是否上市公司": true, "部门": [ { "名称": "研发部", "人数": 50, "主管": "李四" }, { "名称": "市场部", "人数": 30, "主管": "王五" } ], "地址": { "城市": "上海", "街道": "浦东新区张江路123号", "邮编": "201203" }, "联系电话": ["021-12345678", "400-888-9999"] } **这个例子包含了:** - 顶层的对象(公司信息) - 字符串(公司名称、部门名称等) - 数字(成立年份、人数) - 布尔值(是否上市公司) - 数组(部门列表、联系电话列表) - 嵌套的对象(地址信息) - 数组中的对象(每个部门的信息) JSON的“潜规则”:没有注释! ------------------------------ 这是JSON最让人意外的一点:**标准的JSON格式不支持注释**。 是的,您没看错。在JSON文件中,您不能像在代码中那样写 `// 这是注释` 或 `/* 这是注释 */`。 为什么JSON不支持注释? ^^^^^^^^^^^^^^^^^^^^^^^^^^ JSON的设计者道格拉斯·克罗克福德有他的理由: 1. JSON是**数据交换格式**,不是配置文件格式。数据本身不应该携带解释自己的说明。 2. 注释可能被误用,比如包含重要的配置信息,导致解析器需要特殊处理。 3. 保持解析器的简单性。 人们怎么“绕过”这个问题? ^^^^^^^^^^^^^^^^^^^^^^^^^^ 虽然JSON标准不支持注释,但在实际使用中,人们还是需要注释来解释复杂的数据结构。于是出现了几种变通方法: 方法1:使用特殊的属性名作为“伪注释” """"""""""""""""""""""""""""""""""""""""""" .. code-block:: json { "_comment": "这是一条注释,通过特殊的属性名实现", "姓名": "张三", "_note": "电话号码是必填项", "电话": "13800138000" } **优点**:简单,所有JSON解析器都能处理。 **缺点**:注释变成了数据的一部分,可能会被程序误读。 方法2:使用JSON5(JSON的扩展) """"""""""""""""""""""""""""""""""""""""""" JSON5是JSON的扩展,添加了很多便利特性,其中就包括注释: .. code-block:: javascript { // 这是一行单行注释 "姓名": "张三", /* 这是一个 多行注释 */ "电话": "13800138000", 年龄: 30, // 属性名可以不用引号(在JSON5中) '地址': '北京', // 允许使用单引号 已婚: true, 孩子: null } **JSON5的主要扩展特性:** - 支持单行注释(`//`)和多行注释(`/* */`) - 属性名可以不用引号(如果没有特殊字符) - 允许尾随逗号(数组或对象的最后一个元素后面可以加逗号) - 字符串可以用单引号 - 数字可以写成十六进制、有前导小数点等 **注意**:JSON5不是标准JSON,需要使用支持JSON5的解析器才能正确读取。 方法3:在数据处理前移除注释 """"""""""""""""""""""""""""""""""""""""""" 一些工具链会在处理JSON文件前,先用预处理器移除所有注释。这样开发者可以在源文件中写注释,但最终传输或存储的是没有注释的标准JSON。 JSON的优缺点 ------------- 优点: ^^^^^^^^^^^^^^^^^^^^^^^^^^ 1. **人类可读**:相比于XML,JSON更简洁,更容易被人眼阅读和理解。 2. **机器友好**:几乎所有编程语言都有成熟的JSON解析库,处理起来非常高效。 3. **轻量级**:没有像XML那样的冗余标签,文件体积相对较小。 4. **结构清晰**:对象和数组的嵌套可以表示复杂的数据结构。 5. **广泛支持**:已成为Web API的事实标准,绝大多数网络服务都使用JSON。 缺点: ^^^^^^^^^^^^^^^^^^^^^^^^^^ 1. **没有注释**:如上所述,标准JSON不支持注释。 2. **数据类型有限**:没有日期时间类型(通常用字符串表示)、没有二进制数据类型。 3. **严格的语法**:一个多余的逗号、一个缺失的双引号都会导致整个文件解析失败。 4. **不支持循环引用**:不能表示A引用B,B又引用A这样的数据结构。 JSON与相似格式的比较 --------------------- .. csv-table:: JSON与其他格式的简单比较 :header: "特性", "JSON", "YAML", "XML", "CSV" :widths: 15, 20, 20, 20, 25 "主要用途", "数据交换、配置", "配置、数据序列化", "文档标记、数据交换", "表格数据交换" "可读性", "很好", "极好", "一般(冗余标签多)", "好(简单表格)" "注释支持", "不支持", "支持", "支持", "有限支持" "数据类型", "基本类型+对象+数组", "丰富类型", "只有文本(类型需额外定义)", "只有文本" "语法严格度", "非常严格", "严格(对缩进敏感)", "严格", "相对宽松" "文件大小", "较小", "较小", "较大", "最小" "学习曲线", "平缓", "中等", "中等", "平缓" 什么时候应该使用JSON? ----------------------- 使用JSON的场景: ^^^^^^^^^^^^^^^^^^^^^^^^^^ 1. **Web API**:前后端通信、微服务之间的数据交换。 2. **配置文件**:很多现代软件用JSON作为配置文件格式(如VS Code的settings.json)。 3. **数据存储**:NoSQL数据库(如MongoDB)使用类JSON的格式存储数据。 4. **日志记录**:结构化的日志信息。 5. **消息队列**:在系统间传递结构化的消息。 ### 不应该使用JSON的场景: ^^^^^^^^^^^^^^^^^^^^^^^^^^ 1. **需要大量注释的配置**:考虑使用YAML或TOML。 2. **处理二进制数据**:考虑使用专门的二进制格式。 3. **需要复杂文档结构**:考虑使用XML(如Office文档)。 4. **简单的键值对配置**:考虑使用INI或环境变量。 实际应用中的小技巧 ------------------- 1. 格式化与验证 ^^^^^^^^^^^^^^^^^^^^^^^^^^ JSON对格式要求严格,以下工具可以帮助您: - **格式化工具**:让压缩在一行的JSON变得易读(很多在线工具和编辑器插件)。 - **验证工具**:检查JSON语法是否正确(如[jsonlint.com](https://jsonlint.com))。 2. JSON Schema ^^^^^^^^^^^^^^^^^^^^^^^^^^ 如果您需要定义JSON数据的结构(哪些字段是必需的、字段的类型等),可以使用JSON Schema。它本身也是用JSON写的,用来描述和验证JSON数据的结构。 .. code-block:: json { "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "properties": { "姓名": { "type": "string" }, "年龄": { "type": "number", "minimum": 0 } }, "required": ["姓名"] } 这个Schema定义了一个对象,必须有"姓名"字段(字符串类型),可以有"年龄"字段(数字类型,最小值为0)。 3. 处理JSON的程序代码示例 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 几乎每种编程语言都能轻松处理JSON: **Python示例:** .. code-block:: python import json # 将Python字典转换为JSON字符串 data = {"姓名": "张三", "年龄": 30} json_string = json.dumps(data, ensure_ascii=False, indent=2) print(json_string) # 将JSON字符串解析为Python字典 parsed_data = json.loads(json_string) print(parsed_data["姓名"]) # 输出:张三 **JavaScript示例:** .. code-block:: javascript // 将JavaScript对象转换为JSON字符串 let data = {姓名: "张三", 年龄: 30}; let jsonString = JSON.stringify(data, null, 2); console.log(jsonString); // 将JSON字符串解析为JavaScript对象 let parsedData = JSON.parse(jsonString); console.log(parsedData.姓名); // 输出:张三 总结 ----- JSON是一种简洁、高效、通用的数据交换格式。它的核心是两种结构: **对象** (带标签的键值对集合)和**数组**(有序的值列表),配合几种基本数据类型(字符串、数字、布尔值、null)。 虽然JSON不支持注释这一点常常让人感到不便,但这也促使它保持了简单性和一致性。在实际应用中,您可以通过添加特殊字段、使用JSON5扩展,或在工具链中预处理等方式来解决注释问题。 无论您是开发Web应用、编写配置文件,还是在不同系统间传递数据,JSON都是一个可靠的选择。它已经成为了现代软件开发中不可或缺的一部分,就像螺丝钉和胶水一样,虽然不起眼,但却无处不在,连接着数字世界的各个部分。 **最后的小测试** :如果您看到这样的文本,能认出它是JSON吗? .. code-block:: json {"quiz": {"问题": "JSON是什么?", "答案": "一种数据交换格式"}} 是的,这就是一个合法的JSON对象!现在您已经了解了它的基本规则。