1. 开场三问
- 你经历过「字段忽然改名/消失/类型全变」的 500 吗?
- 你经历过「上线前 1 天,后端说少传 3 个字段」吗?
- 你经历过「本地 Mock 完美,联调直接白屏」吗?
只要有一个 Yes,本质只有一句话:接口文档没对清楚。
2. 为什么要「对清楚」
| 维度 | 对清楚 | 没对清楚 |
|---|---|---|
| 开发节奏 | 前端先行,零等待 | 等接口→Mock→再改→再联调 |
| 联调时长 | 1 天 | 3~5 天起跳 |
| 心情 | 优雅下班 | 互相甩锅到凌晨 |
3. 对不清的常见场景(含 Demo)
约定:✅ 正确示例 ❌ 错误/模糊示例
3.1 字段语义歧义
| 场景 | ❌ 模糊 | ✅ 精确 |
|---|---|---|
| 时间含义 | createTime | createTime string 创建时间(yyyy-MM-dd HH:mm:ss) 服务端系统时间 |
| 余额单位 | amount | amount string 单位:元,2 位小数,负值表示欠款 |
| 状态码 | status | status number 0-待审批 1-审批中 2-已通过 3-已拒绝 4-已撤回 |
Demo:前端把
amount=100当「分」传,后端按「元」扣款,1 元秒变 100 元。
3.2 类型与格式歧义
| 场景 | ❌ 模糊 | ✅ 精确 |
|---|---|---|
| 大整数 | id number | id string 雪花ID,Java Long 超 JS 安全范围,必须 string |
| 日期数组 | dates array | dates string[] 元素格式 yyyy-MM-dd,无时分秒,而不是时间戳类型数组 |
| 枚举值 | gender string | gender string M-男 F-女,新增值向后兼容,不删旧值 |
Demo:后端返回
id=1558353858537836545number类型前端 JSON.parse 会丢失精度
3.3 空值策略没对齐
| 场景 | ❌ 模糊 | ✅ 精确 |
|---|---|---|
| 空数组 | attachments array | attachments array 无数据返回 [],不会返回 null |
| 缺字段 | remark | remark string 允许缺失,缺失等价于 "" |
| 布尔 | needNotify | needNotify boolean 永远非 null,默认 false |
Demo:表格组件期待
[],后端给null,前端.length直接抛红。
3.4 分页/排序/过滤二义性
| 场景 | ❌ 模糊 | ✅ 精确 |
|---|---|---|
| 页码起点 | page number | page number 从 1 开始,与 Element-UI 一致 |
| 排序字段 | sort string | sort string 允许值:createTime、status,大小写敏感 |
| 过滤空串 | keyword | keyword string 纯空格按无效处理,后端自动 trim |
Demo:前端传
page=0想拿第一页,后端按page=1算,结果拿重数据。
3.5 错误码与提示文案
| 场景 | ❌ 模糊 | ✅ 精确 |
|---|---|---|
| 错误码 | 400 | 40014 余额不足;40015 状态已终态 |
| 文案变量 | message string | message string 模板:余额不足,当前:{remaining} 元 |
| 国际化 | message | message 仅返回 i18n key,前端按语言包渲染 |
3.6 变更通知机制缺失
| 场景 | ❌ 模糊 | ✅ 精确 |
|---|---|---|
| 字段新增 | 口头群消息 | 文档顶部加「ChangeLog 表」+ 飞书机器人自动推送 |
| 字段废弃 | 直接删 | 先标记 @Deprecated 三个版本,返回头带 X-Deprecated: fieldName |
| 路径变更 | 直接换 | 老路径 301 重定向至少保持 1 个发布窗口 |
3.7 扩展性与维护性
| 场景 | ❌ 反面教材 | ✅ 正面教材 |
|---|---|---|
| 一接口多职 | /submit 既保存草稿又提交审批,flag 区分 | 拆成 /draft/save、/instance/submit |
| 重复轮子 | 类似功能重复设计接口 | 如果业务场景几乎一样,功能也一样,可共用相同接口 |
| 未来扩展性差 | 设计时没留扩展参数或返回值 | 后期想加一个“紧急程度”字段,接口可扩展 |
Demo:万能
/submit加flag=4等参数区分场景,前端 if/else 爆炸,重构=二次开发。
3.8 参数约定——数组/Object,这两种数据类型JSON.parse转换或遍历前后端都容易引发bug
| 场景 | ❌ 模糊 | ✅ 精确 |
|---|---|---|
| 数组空值 | items array | items string[] 不允许 null,无数据=[],元素不可=""等基本类型表示 |
| 对象空值 | address object | address object 允许 null,缺失=null,{} 同样按 null 处理 |
Demo:后端
items:null,前端.forEach炸;约定「无数据=[]」后.forEach放心用。
3.9 新功能 × 历史数据兼容性
| 场景 | ❌ 忽视兼容 | ✅ 兼容方案 |
|---|---|---|
| 必填新字段 | 历史数据存在为null的必填字段,但是没有通知前端 | 1. 提供默认值;2. 灰度脚本刷历史;3. 接口先兼容缺失 |
| 类型兼容 | 历史数据类型不一致 | 1. 灰度脚本刷历史,2. 接口转换 |
4. 其它场景
如果你开发的是审批流等其它业务,可能还有诸多与项目相关的业务场景需要在接口文档体现出来,以审批流为例,并且要兼容多个版本,那么需要特别说明:
- V1 版本特定接口
- V2 版本特定接口
- 多个版本都能共用的接口
5. 结束语
如果想要在工作中减少不确定性,那么尽可能的在前期做好确定性的工作。千万不要觉得对接文档是一件随意的事,这件事涉及你将来是否需要加班联调,出了问题责任归属或甩锅,乃至于未来代码可维护等等。谨以此文,希望引起大家的重视。