高级 JSON 结构和设计模式
掌握高级 JSON 设计模式。学习规范化、多态性、版本控制和可扩展应用的 API 响应模式。
Big JSON Team
• Technical WriterExpert in JSON data manipulation, API development, and web technologies. Passionate about creating tools that make developers' lives easier.
# 高级 JSON 结构和设计模式
本指南涵盖了创建可扩展、可维护的 JSON 结构的高级技术和模式。
嵌套 vs 扁平结构
过度嵌套(❌ 避免)
{
"id": 1,
"user": {
"profile": {
"personal": {
"contact": {
"email": "user@example.com"
}
}
}
}
}
问题:
- 难以查询
- 深度路径
- 重序列化困难
过度扁平(❌ 避免)
{
"id": 1,
"user_profile_personal_contact_email": "user@example.com",
"user_profile_personal_contact_phone": "123456"
}
问题:
- 键名冗长
- 逻辑关系不清楚
- 难以维护
平衡的方法(✅ 推荐)
{
"id": 1,
"name": "张三",
"email": "zhang@example.com",
"profile": {
"bio": "开发者",
"avatar": "https://example.com/avatar.jpg"
},
"address": {
"city": "北京",
"country": "中国"
}
}
原则:
- 最多 3-4 级深度
- 逻辑相关的数据组合
- 避免不必要的嵌套
数据规范化
规范化是组织 JSON 数据以避免冗余的技术。
反规范化(嵌入式)
{
"orders": [
{
"id": 1,
"customerId": 101,
"customer": {
"id": 101,
"name": "张三",
"email": "zhang@example.com"
},
"items": [
{
"productId": 1,
"product": {
"id": 1,
"name": "笔记本",
"price": 1200
}
}
]
}
]
}
优点:
- ✅ 减少数据库查询
- ✅ 单个请求获取所有数据
- ✅ 简单的前端逻辑
- ❌ 数据重复
- ❌ 更新困难
- ❌ 文件大小更大
- 读取频繁
- 写入罕见
- 小到中等数据集
规范化(引用)
{
"orders": [
{
"id": 1,
"customerId": 101,
"items": [1, 2, 3]
}
],
"customers": {
"101": {
"id": 101,
"name": "张三",
"email": "zhang@example.com"
}
},
"products": {
"1": {
"id": 1,
"name": "笔记本",
"price": 1200
}
}
}
优点:
- ✅ 无数据重复
- ✅ 易于更新
- ✅ 更小的文件大小
- ❌ 需要多个查询
- ❌ 前端需要合并数据
- ❌ 更复杂的逻辑
- 频繁更新
- 大型数据集
- 分布式系统
API 响应模式
信封模式(推荐)
{
"success": true,
"data": {
"id": 1,
"name": "张三"
},
"meta": {
"timestamp": "2026-01-15T10:00:00Z",
"version": "1.0"
}
}
分页响应
{
"success": true,
"data": [
{"id": 1, "name": "张三"},
{"id": 2, "name": "李四"}
],
"pagination": {
"page": 1,
"pageSize": 10,
"total": 100,
"totalPages": 10,
"hasNext": true,
"hasPrev": false
}
}
错误响应
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "输入验证失败",
"details": [
{
"field": "email",
"message": "无效的电子邮件格式"
},
{
"field": "age",
"message": "年龄必须 >= 18"
}
]
},
"timestamp": "2026-01-15T10:00:00Z"
}
列表响应
{
"success": true,
"data": [
{"id": 1, "name": "项目1"},
{"id": 2, "name": "项目2"}
],
"meta": {
"count": 2,
"filtered": false
}
}
多态性模式
多态性允许单个字段包含不同类型的数据。
使用 type 字段(推荐)
{
"notifications": [
{
"id": 1,
"type": "email",
"data": {
"to": "user@example.com",
"subject": "欢迎"
}
},
{
"id": 2,
"type": "sms",
"data": {
"phone": "+86 138 1234 5678",
"message": "验证码: 123456"
}
},
{
"id": 3,
"type": "push",
"data": {
"title": "新消息",
"body": "你有新的消息"
}
}
]
}
TypeScript 中的类型
type Notification = EmailNotification | SmsNotification | PushNotification;
interface EmailNotification {
id: number;
type: 'email';
data: {
to: string;
subject: string;
};
}
interface SmsNotification {
id: number;
type: 'sms';
data: {
phone: string;
message: string;
};
}
interface PushNotification {
id: number;
type: 'push';
data: {
title: string;
body: string;
};
}
// 使用
function handleNotification(notif: Notification) {
switch (notif.type) {
case 'email':
sendEmail(notif.data.to, notif.data.subject);
break;
case 'sms':
sendSms(notif.data.phone, notif.data.message);
break;
case 'push':
sendPushNotification(notif.data.title, notif.data.body);
break;
}
}
版本控制
API 的版本控制对于向后兼容很重要。
版本字段
{
"version": "2.0",
"data": {
"users": [...]
}
}
版本化数据结构
{
"apiVersion": "v2",
"user": {
"v1": {
"id": 1,
"name": "张三"
},
"v2": {
"id": 1,
"firstName": "张",
"lastName": "三",
"email": "zhang@example.com"
}
}
}
迁移策略
// 处理多个版本
function parseResponse(response) {
if (response.version === '1.0') {
return migrateV1ToV2(response.data);
} else if (response.version === '2.0') {
return response.data;
}
}
function migrateV1ToV2(data) {
return {
...data,
email: data.contact?.email || null,
phone: data.contact?.phone || null
};
}
可选性和缺省值
明确的可选字段
{
"id": 1,
"name": "张三",
"optional": {
"middleName": null,
"nickname": null,
"phone": null
}
}
带有缺省值的配置
{
"settings": {
"theme": "dark",
"notifications": {
"enabled": true,
"frequency": "daily"
},
"privacy": {
"publicProfile": false
}
},
"defaults": {
"theme": "light",
"notifications.enabled": false,
"privacy.publicProfile": true
}
}
链接和关系
HAL(超文本应用语言)模式
{
"id": 1,
"name": "张三",
"_links": {
"self": {
"href": "/users/1"
},
"posts": {
"href": "/users/1/posts"
},
"comments": {
"href": "/users/1/comments"
}
}
}
JSON:API 模式
{
"data": {
"type": "users",
"id": "1",
"attributes": {
"name": "张三",
"email": "zhang@example.com"
},
"relationships": {
"posts": {
"data": [
{"type": "posts", "id": "1"},
{"type": "posts", "id": "2"}
]
}
}
},
"included": [
{
"type": "posts",
"id": "1",
"attributes": {
"title": "第一篇文章"
}
}
]
}
大文件优化
对于包含大数据集的响应:
分页
{
"data": [...],
"pagination": {
"page": 1,
"pageSize": 20,
"total": 1000
}
}
游标分页
{
"data": [...],
"cursor": {
"next": "eyJpZCI6IDEwMH0=",
"previous": null
}
}
指流
// Server-sent Events(SSE));app.get('/stream/data', (req, res) => {
res.setHeader('Content-Type', 'text/event-stream');
for (let i = 0; i < 1000; i++) {
res.write(
data: ${JSON.stringify({id: i, value: Math.random()})}}
});
安全的 JSON 结构
避免敏感数据泄露
{
"user": {
"id": 1,
"name": "张三",
"email": "zhang@example.com",
"passwordHash": "..." // ❌ 不要暴露
}
}
// ✅ 正确:过滤敏感字段
{
"user": {
"id": 1,
"name": "张三",
"email": "zhang@example.com"
}
}
使用适当的权限
{
"user": {
"id": 1,
"name": "张三",
"isAdmin": false,
"permissions": ["read", "write"]
}
}
性能优化
字段过滤
// API 端点支持字段选择
GET /users/1?fields=id,name,email
// 返回:
{
"id": 1,
"name": "张三",
"email": "zhang@example.com"
}
聚合
// 支持聚合调用
GET /aggregate?include=user,posts,comments
// 单个请求获取所有相关数据
{
"user": {...},
"posts": [...],
"comments": [...]
}
最佳实践总结
设计原则
检查清单
□ 嵌套深度最多 3-4 级
□ 避免数据重复
□ 使用清晰的字段名
□ 包含元数据(时间戳、版本)
□ 错误响应一致
□ 支持分页
□ 不暴露敏感数据
□ 有关系链接
□ 支持可选字段
□ 文档化结构
结论
设计好的 JSON 结构是高质量 API 的基础。遵循这些模式和最佳实践,创建可扩展、可维护的数据结构。
选择适合您需求的模式,并在整个项目中保持一致!