规范原则

  • 接口返回数据即展示:前端仅做渲染逻辑的处理;
  • 渲染逻辑禁止夸多个接口调用;
  • 前端关注交互、渲染逻辑,尽量避免业务逻辑处理的出现;
  • 请求数据传输格式:RESTful API 风格
  • 响应数据传输格式:JSON 数据尽量简单轻量,避免多级JSON的出现;

    请求数据格式(RESTful)

    理解 RESTful

    版本号

    在 RESTful API 中,API 接口应该尽量兼容之前的版本。但是,在实际业务开发场景中,可能随着业务需求的不断迭代,现有的 API 接口无法支持旧版本的适配,此时如果强制升级服务端的 API 接口将导致客户端旧有功能出现故障。实际上,Web 端是部署在服务器,因此它可以很容易为了适配服务端的新的 API 接口进行版本升级,然而像 Android 端、IOS 端、PC 端等其他客户端是运行在用户的机器上,因此当前产品很难做到适配新的服务端的 API 接口,从而出现功能故障,这种情况下,用户必须升级产品到最新的版本才能正常使用。
    为了解决这个版本不兼容问题,在设计 RESTful API 的一种实用的做法是使用版本号。一般情况下,我们会在 url 中保留版本号,并同时兼容多个版本。
    1. GET /v1/users/{user_id} // 版本 v1 的查询用户列表的 API 接口
    2. GET /v2/users/{user_id} // 版本 v2 的查询用户列表的 API 接口

现在,我们可以不改变版本 v1 的查询用户列表的 API 接口的情况下,新增版本 v2 的查询用户列表的 API 接口以满足新的业务需求,此时,客户端的产品的新功能将请求新的服务端的 API 接口地址。虽然服务端会同时兼容多个版本,但是同时维护太多版本对于服务端而言是个不小的负担,因为服务端要维护多套代码。这种情况下,常见的做法不是维护所有的兼容版本,而是只维护最新的几个兼容版本,例如维护最新的三个兼容版本。在一段时间后,当绝大多数用户升级到较新的版本后,废弃一些使用量较少的服务端的老版本API 接口版本,并要求使用产品的非常旧的版本的用户强制升级。
注意的是,“不改变版本 v1 的查询用户列表的 API 接口”主要指的是对于客户端的调用者而言它看起来是没有改变。而实际上,如果业务变化太大,服务端的开发人员需要对旧版本的 API 接口使用适配器模式将请求适配到新的API 接口上。

资源路径

RESTful API 的设计以资源为核心,每一个 URI 代表一种资源。因此,URI 不能包含动词,只能是名词。注意的是,形容词也是可以使用的,但是尽量少用。一般来说,不论资源是单个还是多个,API 的名词要以复数进行命名。此外,命名名词的时候,要使用小写、数字及下划线来区分多个单词。这样的设计是为了与 json 对象及属性的命名方案保持一致。例如,一个查询系统标签的接口可以进行如下设计。

【GET】  /v1/tags/{tag_id}

同时,资源的路径应该从根到子依次如下

/{resources}/{resource_id}/{sub_resources}/{sub_resource_id}/{sub_resource_property}

我们来看一个“添加用户的角色”的设计,其中“用户”是主资源,“角色”是子资源。

【POST】  /v1/users/{user_id}/roles/{role_id} // 添加用户的角色

有的时候,当一个资源变化难以使用标准的 RESTful API 来命名,可以考虑使用一些特殊的 actions 命名。

/{resources}/{resource_id}/actions/{action}

举个例子,“密码修改”这个接口的命名很难完全使用名词来构建路径,此时可以引入 action 命名。

【PUT】  /v1/users/{user_id}/password/actions/modify // 密码修改


请求基本格式

响应实体格式(JSON)

响应基本格式

{
  "code": "S00200",
  "message": "操作成功",
  "sign": 1,
  "body": {}
}
响应字段 字段描述 备注
code 响应代码
message 响应描述
sign 响应标记 1-操作成功,0-操作无结果
body 承载数据

响应实体格式

{
  "code": "S00200",
  "message": "操作成功",
  "sign": 1,
  "body": {
    "sid": "1000000000000000010",
    "remarks": "备注",
    "createTime": "2021-03-12 18:48:08",
    "enable": 1
  }
}
响应字段 字段描述 备注
code 响应代码
message 响应描述
sign 响应标记 1-操作成功,0-无承载数据
body 承载数据 实体数据内容

响应列表格式

{
  "code": "S00200",
  "message": "操作成功",
  "sign": 1,
  "body": [
    {
      "typeCode": "SYS00003",
      "value": "0",
      "desc": "女",
      "sort": 3,
      "dictDefault": 0
    },
    {
      "typeCode": "SYS00003",
      "value": "1",
      "desc": "男",
      "sort": 3,
      "dictDefault": 0
    }
  ]
}
响应字段 字段描述 备注
code 响应代码
message 响应描述
sign 操作标记 1-操作成功,0-无承载数据
body 承载数据 列表数据内容

响应分页格式

{
  "code": "S00200",
  "message": "操作成功",
  "sign": true,
  "body": {
    "rows": [
      {
        "sid": 1000000000000000001,
        "name": '张三',
      },
      {
        "sid": 1000000000000000002,
        "name": '李四'
      }
    ],
    "total": 10,
    "pages": 1,
    "page": 1,
    "limit": 10
  }
}
响应字段 字段描述 备注
code 响应代码
message 响应描述
sign 操作标记 1-操作成功,0-无承载数据
body 承载数据
rows 列表数据
total 数据总数
pages 总页数
page 当前页码
limit 偏移量(每页条数)

特殊内容规范

下拉框、复选框、单选框

  • 由后端接口逻辑判定是否选中,通过标识是否选中,示例如下:

    {
    "code": "S00200",
    "message": "操作成功",
    "sign": 1,
    "body": [
      {
        "value": "0",
        "desc": "女",
        "sort": 3,
        "defaultValue": 0
      },
      {
        "value": "1",
        "desc": "男",
        "sort": 3,
        "defaultValue": 0
      },
      {
        "value": "2",
        "desc": "未知",
        "sort": 3,
        "defaultValue": 1
      }
    ]
    }
    

    Boolean类型

  • JSON数据传输中一律使用1、0来表示,1=true/是,0=false/否

    后端在通用模块中配置,基础JSON转换

日期格式

  • 关于日期格式,JSON传输中一律使用字符串,正常情况下默认为此格式:
    • 时间:HH:mm:ss
    • 年月日:yyyy-MM-dd
    • 年月日时分秒:yyyy-MM-dd HH:mm:ss
{
  "code": "S00200",
  "message": "操作成功",
  "sign": 1,
  "body": {
    "localDateTime": "2021-11-18 14:45:00",
    "localDate": "2021-11-18",
    "localTime": "14:45:00"
  }
}

异常信息