JSON
→ 返回 计算机网络
JSON(JavaScript Object Notation)是一种轻量级的文本数据交换格式,语法源于 JavaScript 对象字面量,因可读性好、语言无关,成为前后端交互和配置文件的事实标准。
数据类型
| 类型 | 示例 |
|---|---|
| 字符串 | "hello" |
| 数字 | 42、3.14、-1 |
| 布尔值 | true、false |
| 空值 | null |
| 数组 | [1, "two", true] |
| 对象 | {"key": "value"} |
语法规则
{
"name": "Alice",
"age": 30,
"isAdmin": false,
"tags": ["java", "spring"],
"address": {
"city": "Beijing",
"zip": "100000"
},
"avatar": null
}- 键名必须用双引号包裹
- 字符串值用双引号,不可用单引号
- 末尾不允许有多余逗号(trailing comma)
- 不支持注释
常用操作
JavaScript
// 序列化:对象 → JSON 字符串
const json = JSON.stringify({ name: 'Alice', age: 30 })
// 格式化输出
const pretty = JSON.stringify(obj, null, 2)
// 反序列化:JSON 字符串 → 对象
const obj = JSON.parse('{"name":"Alice","age":30}')
// 深拷贝(简单场景)
const copy = JSON.parse(JSON.stringify(original))Java(Jackson)
ObjectMapper mapper = new ObjectMapper();
// 序列化
String json = mapper.writeValueAsString(user);
// 反序列化
User user = mapper.readValue(json, User.class);
// 忽略未知字段
@JsonIgnoreProperties(ignoreUnknown = true)
public class User { ... }Python
import json
# 序列化
json_str = json.dumps({"name": "Alice", "age": 30}, ensure_ascii=False)
# 反序列化
obj = json.loads(json_str)
# 读写文件
with open("data.json", "w") as f:
json.dump(data, f, ensure_ascii=False, indent=2)JSON vs 其他格式
| 格式 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| JSON | 可读性好,语言支持广 | 体积偏大,无注释 | REST API,配置文件 |
| XML | 结构严谨,支持 schema | 冗余标签,解析慢 | 传统 SOAP,文档型数据 |
| YAML | 可读性最好,支持注释 | 缩进敏感,解析复杂 | 配置文件(Docker、K8s) |
| Protobuf | 体积小,解析快 | 二进制不可读,需 schema | gRPC,高性能微服务 |
常见语言操作补充
Go
import "encoding/json"
type User struct {
Name string `json:"name"`
Age int `json:"age"`
Email string `json:"email,omitempty"` // 空值时省略
}
// 序列化
data, err := json.Marshal(User{Name: "Alice", Age: 30})
// 格式化
data, err := json.MarshalIndent(user, "", " ")
// 反序列化
var u User
err = json.Unmarshal([]byte(jsonStr), &u)
// 流式解码(大文件)
decoder := json.NewDecoder(r)
decoder.Decode(&u)TypeScript
// 类型安全的反序列化(运行时无校验,需手动断言或用 zod)
interface User { name: string; age: number }
const user = JSON.parse(jsonStr) as User
// 使用 zod 进行运行时校验
import { z } from 'zod'
const UserSchema = z.object({ name: z.string(), age: z.number() })
const user = UserSchema.parse(JSON.parse(jsonStr)) // 类型错误时抛出JSON Schema
用 JSON 描述 JSON 结构,用于校验数据合法性:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"name": { "type": "string", "minLength": 1 },
"age": { "type": "integer", "minimum": 0, "maximum": 150 }
},
"required": ["name", "age"]
}常用工具:ajv(Node.js)、jsonschema(Python)、Jackson 的 @Valid 集成。
NDJSON / JSON Lines
每行一个独立 JSON 对象,适合流式处理和日志:
{"id":1,"event":"login","user":"alice"}
{"id":2,"event":"purchase","amount":99.9}
{"id":3,"event":"logout","user":"alice"}优势:逐行读取无需加载全部数据到内存,适合日志收集(Logstash、Kafka)。
注意事项
- 数字精度:超过 53 位整数(Java Long)传给 JS 会丢失精度,应转为字符串
- 日期:JSON 无原生日期类型,通常用 ISO 8601 字符串(
"2024-01-01T00:00:00Z")或时间戳(毫秒数) - null vs 缺失字段:
"field": null与不包含该字段语义不同,序列化时需注意 - 循环引用:
JSON.stringify遇到循环引用会抛出,需先处理或使用replacer - 特殊浮点数:
NaN、Infinity、-Infinity在 JSON 中无效,序列化结果为null
安全注意事项
| 问题 | 说明 | 防护 |
|---|---|---|
| Prototype 污染 | {"__proto__": {"isAdmin": true}} 篡改原型链 | 使用 Object.create(null) 或安全解析库 |
| JSON 注入 | 用户输入直接拼接进 JSON 字符串 | 始终使用序列化库,不手动拼接 |
| 敏感字段泄露 | 序列化时包含密码、Token 等字段 | 使用 @JsonIgnore / omitempty 排除敏感字段 |
| 超大 JSON 解析 | 恶意超大 JSON 耗尽内存 | 设置最大 Body 大小,使用流式解析 |