公开 API 兼容性与版本迁移
公开 API 的数据会随着网页功能增加而演进。稳定客户端应依赖公开字段和页面行为,不应依赖源码中的隐藏名称、未记录端点或某一次响应的字段顺序。
兼容性原则
对新增字段保持容忍
读取对象时忽略未知字段,但保存备份或转发对象时保留它们。新增字段不应导致旧客户端崩溃,也不应因为旧客户端不认识就自动删除。
对缺失字段使用明确默认值
缺失与空字符串、0、false 不是同一件事。显示层可以把缺失标成“未提供”,但不要静默改写为 0 再写回服务。
不依赖字段顺序
JSON 对象字段顺序不保证稳定。列表排序应由页面约定、时间字段或用户选择决定,不要用响应文本顺序推断优先级。
不猜测配置名
配方页面只显示当前账号可见的配置。客户端应读取并呈现服务返回的名称;未知名称可以只读显示,不能从源码或聊天记录推断隐藏配置后直接写入。
请求兼容性
把以下内容集中在一个可配置层:
- API 基础地址;
- API 版本路径;
- 请求超时;
- 默认页大小;
- 是否允许自定义地址;
- 公开功能开关。
不要把地址复制到多个页面,也不要把服务地址拼进用户可见日志。自定义地址只在当前页面明确允许且用户拥有授权时使用。
响应兼容性
布尔结果
兼容客户端应同时支持业务成功封装和 Token 验证结果:
写入/删除类:success + msg
验证类:valid + expires_at/expired
列表类:success + data/list 字段
文件类:Content-Type + 二进制或 JSON如果返回结构不符合上述已记录形态,显示“响应格式不兼容”,不要把它当成成功。
时间字段
优先解析带时区的 RFC3339 时间。没有时区的字符串不得直接当成本地时间写回;页面应显示原文或要求用户确认时区。
数字和枚举
数字字段要验证有限性、范围和单位。枚举字段保留未知值并显示“未知/新版本值”,不要强行映射到已有选项。达成率、时长、进度和版本号的单位不同,不能复用同一个格式化器。
客户端升级策略
只读兼容升级
先发布只读版本,验证:
- Token 验证;
- 主页和统计;
- 列表、分页和文件响应;
- 空状态和错误状态;
- 未知字段展示。
确认读取稳定后,再启用保存、删除和恢复入口。
写入兼容升级
写入功能必须具备:
- 原值预览;
- 本地格式校验;
- 明确的确认文案;
- 保存中锁定;
- 成功后重新读取;
- 失败不覆盖本地原值;
- 超时后的状态核对。
不能因为新增字段未知就提交一份删减后的完整对象。
版本差异排查
当网页和客户端结果不同,按顺序比较:
| 项目 | 问题 |
|---|---|
| 基础地址 | 是否使用同一个服务入口 |
| API 版本 | 路径是否一致 |
| 账号类型 | 用户/机台权限是否一致 |
| Token | 是否仍然有效、是否来自同一账号 |
| 请求体 | 字段类型和必填项是否一致 |
| Content-Type | 是否为 JSON 或文件接口要求的类型 |
| 时间范围 | 是否读取了同一范围 |
| 本地缓存 | 是否显示旧数据 |
| 页面状态 | 是否仍处于加载/保存中 |
不要先修改服务端配置来迁就客户端差异;先用浏览器页面作为公开行为基准。
迁移备份
客户端升级前至少保存:
- 当前账号列表的受保护副本;
- 普通缓存 JSON;
- 上传缓存索引和重要快照;
- 必要相片;
- 当前客户端版本、基础地址和导出时间。
恢复时不要跨账号、跨环境或跨未确认版本合并备份。恢复完成后重新读取记录、成绩、相片和配方,记录返回条数和任何未知字段提示。
兼容性测试矩阵
| 场景 | 期望 |
|---|---|
| 新增响应字段 | 客户端仍能读取并保留 |
| 缺少可选字段 | 显示未提供,不崩溃 |
| 新枚举值 | 只读显示未知值 |
| 空数组 | 显示空状态,不报网络错误 |
| JSON 错误 | 显示错误并保留原输入 |
| 二进制文件 | 不调用 JSON 解析 |
| Token 过期 | 停止轮询并要求重登录 |
| 429 | 退避而不是并发重试 |
| 写入超时 | 先重新读取再决定 |
| 地址变更 | 由配置层切换并重新验证 |
发布前检查
- [ ] 文档只引用公开页面和公开 API;
- [ ] 未硬编码隐藏配置名;
- [ ] 未把凭据写入示例、测试夹具或日志;
- [ ] 未丢弃未知字段;
- [ ] 所有写入动作都有回读验证;
- [ ] 文件接口按 Content-Type 分流;
- [ ] 旧版本客户端面对新增字段不崩溃;
- [ ] 新版本客户端面对缺失字段不误写默认值;
- [ ] 基础地址和版本路径可配置;
- [ ] 迁移说明包含备份和回滚步骤。
