json format data web development

JSON 深度解析:从基础语法到高级应用

全面介绍 JSON 的历史起源、语法规范、在现代 Web 开发中的典型使用场景、常见陷阱与最佳实践。

什么是 JSON?

JSON(JavaScript Object Notation,JavaScript 对象表示法)是一种轻量级的文本数据交换格式,既便于人类阅读和编写,也易于机器解析和生成。尽管 JSON 语法源自 JavaScript,但它是语言无关的——几乎所有现代编程语言都提供了解析和生成 JSON 的标准库。

JSON 由 Douglas Crockford 在 21 世纪初提出,作为 XML 的更简洁替代方案用于 Web 数据交换。如今,它已成为 REST API、配置文件、MongoDB 等 NoSQL 数据库以及众多领域的主流格式。


JSON 语法:完整介绍

JSON 值可以是以下类型之一:

  • 对象{ "key": value, ... } — 键值对的无序集合,键必须是字符串
  • 数组[ value, ... ] — 有序值列表
  • 字符串"hello world" — 必须使用双引号
  • 数字423.14-71.5e10 — 不区分整数与浮点数
  • 布尔值truefalse
  • 空值null
{
  "name": "张三",
  "age": 30,
  "isActive": true,
  "scores": [95, 87, 100],
  "address": {
    "city": "北京",
    "district": "海淀区"
  },
  "notes": null
}

常见语法错误

错误类型 错误写法 正确写法
尾部逗号 { "a": 1, } { "a": 1 }
单引号 { 'key': 'val' } { "key": "val" }
键未加引号 { key: "val" } { "key": "val" }
注释 { // 注释 } (JSON 不支持注释)
undefined { "a": undefined } 使用 null 或省略该键

简史

  • 2001 年:Douglas Crockford 开始推广 JSON 作为无状态的服务器到浏览器通信协议
  • 2006 年:IETF 发布 RFC 4627,JSON 的第一个正式规范
  • 2013 年:ECMA International 将 JSON 标准化为 ECMA-404
  • 2017 年:RFC 8259 取代所有先前 RFC,成为权威标准

在 JSON 出现之前,XML 主导了 API 通信。JSON 的简洁性和与 JavaScript 对象的天然契合使其在 Web 2.0 时代迅速普及——这一趋势延续至今。


JSON 的应用场景

REST API

如今几乎所有 REST API 都返回 JSON 格式数据。以天气 API 为例:

{
  "location": "北京",
  "temperature": 26.5,
  "unit": "celsius",
  "conditions": ["晴天", "微风"],
  "forecast": [
    { "day": "周一", "high": 28, "low": 18 },
    { "day": "周二", "high": 25, "low": 16 }
  ]
}

配置文件

ESLint(.eslintrc.json)、TypeScript(tsconfig.json)、npm(package.json)等工具均使用 JSON 作为配置格式。

NoSQL 数据库

MongoDB 以 BSON(Binary JSON)存储文档。CouchDB、Firebase Firestore、DynamoDB 等数据库也采用类 JSON 的文档模型。

浏览器本地存储

浏览器的 localStorage 只能存储字符串,开发者通常在存储前使用 JSON.stringify() 序列化对象,读取时用 JSON.parse() 反序列化。

结构化日志

以 JSON 格式记录日志便于使用 Elasticsearch、Datadog 或 Loki 等工具进行查询分析。


各语言的 JSON 解析

JavaScript / TypeScript

// 解析字符串为对象
const data = JSON.parse('{"name":"张三","age":30}');
console.log(data.name); // "张三"

// 序列化为字符串(美化输出)
const json = JSON.stringify({ name: "张三", age: 30 }, null, 2);

JSON.stringify 的第三个参数 2 表示用 2 个空格缩进,调试时非常实用。

Python

import json

# 解析
data = json.loads('{"name": "张三", "age": 30}')
print(data["name"])  # 张三

# 序列化
text = json.dumps({"name": "张三", "age": 30}, ensure_ascii=False, indent=2)

注意 Python 中需设置 ensure_ascii=False 才能正确输出中文字符。

Go

import (
    "encoding/json"
    "fmt"
)

type Person struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
}

func main() {
    var p Person
    json.Unmarshal([]byte(`{"name":"张三","age":30}`), &p)
    fmt.Println(p.Name)
}

进阶主题

JSON Schema

JSON Schema 是验证 JSON 数据结构的词汇表,可以定义必填字段、值类型、模式和约束:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "name": { "type": "string" },
    "age": { "type": "integer", "minimum": 0 }
  },
  "required": ["name", "age"]
}

JSON Pointer(RFC 6901)

JSON Pointer 提供了一种字符串语法,用于定位 JSON 文档中的特定值:

  • /namename 字段
  • /scores/0scores 数组的第一个元素

JSON Patch(RFC 6902)

JSON Patch 定义了一套对 JSON 文档进行增量更新的操作格式,适用于 API 中的部分更新场景。


性能考量

  • 数据量:JSON 是文本格式,相对冗长。高吞吐场景可考虑 MessagePackProtocol Buffers 等二进制替代方案。
  • 解析速度:现代 JSON 解析器(如 simdjson)每秒可处理数 GB 数据,对大多数 Web 应用而言解析性能不是瓶颈。
  • 深层嵌套:嵌套过深可能导致递归解析器栈溢出,建议保持数据结构尽量扁平。

JSON vs XML vs YAML

特性 JSON XML YAML
可读性 良好 冗长 极佳
支持注释
二进制支持 ❌(需 base64)
Schema 验证 JSON Schema XSD ❌(有限)
最适合 API、配置、存储 文档、历史系统 配置文件

最佳实践

  1. 输入时验证:始终对外部 JSON 输入进行验证,绝不盲目信任。
  2. null 的使用要有意义:区分"字段缺失"与"字段值为 null"。
  3. 避免深层嵌套:扁平化数据结构更易于处理,用 ID 引用关联对象。
  4. 统一键名风格:在整个 API 中选择一种风格(camelCase 或 snake_case)并保持一致。
  5. 日期使用 ISO 8601 字符串:JSON 没有日期类型,推荐使用 "2025-04-09T00:00:00Z" 格式。
  6. 生产环境压缩,调试时美化:API 响应使用紧凑 JSON 以节省带宽;本地调试时使用格式化输出。

小结

JSON 因其简洁性、可读性和广泛的语言支持,已成为 Web 数据交换的通用语言。深入理解 JSON 的语法、局限性和最佳实践,无论是构建 API、编写配置文件还是处理数据管道,都会让你成为更高效的开发者。