服务端 API 接口设计
RESTful API 的设计不做过多介绍,只针对 JSON 型 API 返回结果结构的设计的个人理解;
请求数据返回结构
服务器返回结果的结构示例:
1 | { |
data 字段 - 业务需求数据
请求结果返回的数据 data
字段,为页面显示的具体所有数据,其值类型可以为对象(字典)或数组,据具体业务场景而定,可以灵活组合使用。
如果请求的是用户的个人信息,就可以为字典对象,结构如下:
1 | data : { // 请求返回数据,字典对象 |
如果请求的是列表数据,就可以是数组对象(字典型数组对象),如请求新闻列表:
1 | data: [ |
msg 字段 - 请求状态描述调试数据
msg
字段是本次请求的业务、状态描述信息,用于调试,线上问题定位 debug 以及配合埋点等作用;
1 | msg: "个人信息接口" |
code 字段 - 自定义业务状态码
HTTP 请求本身已经有了完备的状态码, 为什么还要自定义一套状态码呢?如一次成功的 Http status 200 的请求,可能由于用户未登录、登录过期而有不同的返回结果和处理方式,并且根据业务分类自定义状态码更容易去定位问题等等;
状态码的定义服务端应该有一套规范,可以按照用户相关、授权相关、各种业务等等做分类:
1 | // Code 业务自定义状态码定义示例 |
extra字段 - 全局附加数据
extra字段,用来表示全局的附加数据。业务场景用户的操作(数据请求),会导致用户的等级、经验变化,而具体什么时候产生不确定,由服务端的规则决定,并且客户端要及时向用户展示变化,所以加上了extra字段。
在设计extra字段的时候,并没有对其结构内容做限制,所以比较灵活,但是还是要有个type字段,来做约束,如:
1 | // 升级 |
总的来说就是自由发挥,只要服务端、客户端相互沟通好即可。当然,也要避免乱用,保证真的需要全局附加数据才使用这个字段。
请求数据返回值的规范
命名统一规范
命名格式不管是使用驼峰还是下划线命名,只要全部统一就好,个人建议还是使用 _
,看着舒服一点,例如:user_id
、user_name
等;
命名语意尽量做到见名知意,但是别使用拼音真的很 low 而且真的反应不过来;使用常用缩写;
1 | // 字符串 |
空值的处理
空值的处理需慎重,特别容易引起 crash 等问题,服务端与客服端一定要协商好;
统一空值用 null
除了布尔类型的,其余的空值统一用 null
表示,客户端保证每种字段的 null
可以被正常处理。
统一空值不同类型设置默认空值
除了 null
,还可以对字段设置 “默认值”,如数字就是 0,字符串就是空字符串 “”,数组就是空数组[],对象就是空对象 {},这样有个好处就是可以避免很多客户端(Java、OC)处理空值(Null、nil、null)产生的异常。但是危害就是容易语义不明。还是要根据具体业务、前后端约定而定。
布尔 boolean 值的处理
布尔值各种处理见过的有如下几种:
1 | is_login: true, |
由于语言本身的限制、框架的处理方式,不对布尔类型的值做限制总觉得不踏实,像C、C++、Objective-C 里面的布尔就是数字0和1,其它语言也都各自不一样,还有从数据库读写导致的布尔值类型不一致等。
个人习惯性统一为 0 和 1,然后在客户端和服务端统一设置常量、宏定义,定义布尔的类型,所有的参数、结果的布尔字段全部做强制约束。
时间日期值的处理
时间的处理也是非常容易出错的,特别是遇上时区转换的时候。
强制GMT/UTC时间戳
一种做法就是强制所有时间参数只能传 Unix 时间戳,也就是标准 GMT/UTC 时间戳,然后由各自的客户端根据自己的时区、显示要求做处理后显示。
1 | // 从服务器接收的时间数据 |
这样的话,客户端、服务端存储、读取时间都相当于处理纯数字。
使用ISO 8601带时区的时间日期字符串
使用Unix时间戳有个坏处,就是:
最早只能到1970/1/1 0:0:0GMT时间,一旦需求早于这个时间,时间戳就成了负数=。=
不方便人阅读。调试API的时候,开发人员不能直观看出具体时间,很不方便
所以,可以按照ISO 8601标准,用字符串保存、传输时间。
如果以YYYY-MM-DDThh:mm:ssTZD格式为准, 时间的形式就是1997-07-16T19:20:30+01:00,保存了时区信息,也方便阅读。
type 类型的处理
API数据中免不了各种类型字段,如用户类型user_type、登录类型login_type等,类型的表示也可以分为数字、字符串两种。
数字表示类型:这个应该是最直接的方式了,客户端和服务端共同维护某个API下、某个数据类型中的type常量,靠文档约束。
字符串表示类型:数字的类型毕竟不利于直观阅读,如果可以的话,用字符串也是不错的,当然坏处就是代码里面就不能用Switch语句了(除了强大的 Swift =。=)
1 | // 如登录类型,QQ、微信、微博等 |
完整的URL,协议类型
API里面的数据也会有URL类型的,一般来说如用户的头像、各种图片、音频等资源,都是以URL链接的形式返回的。
返回的URL一定要“完整”,主要指的是不要忘记URL里面的协议部分,也就是 scheme 部分。像 xxxx.me/imgs/1.jpg这种URL值,就是不完整的,没有指明网络协议,难道靠猜=。=
总结
嗯,规范非常重要。:-D
参考地址
本文标题:服务端 API 接口设计
文章作者:zerocc
发布时间:2016年08月15日
原始链接:http://www.zerocc.com.cn/2016081501.html
版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 CN 许可协议。转载请注明出处!
分享