Web 技术研究所

我一直坚信着,Web 将会成为未来应用程序的主流

REST API 设计之 —— 内容格式

  请求成功后,如果有内容,大致可以分为两种情形。一种是列表数据,另一种则是单一数据。在非 REST 的 API 设计中,由于响应要考虑错误信息,所以通常都给响应的数据包裹一层对象;而 REST API 有自己的错误处理方式,响应的内容完全可以无加工地直接传输。

单一数据的格式

  对于单一数据,唯一的问题就是格式。比如查询结果是一个数字,那么服务器就直接响应一个数字?虽然数字本身也属于 JSON 的范畴,但考虑到广义与狭义 JSON 的概念差异,我还是建议将服务器响应的内容统一为狭义 JSON 以获得更多的兼容支持。

列表包裹对象的纠结

  比起单一数据,列表数据才是最纠结的。主要的纠结点是列表数据要不要包裹一层对象。之前和 @lepture 大神讨论过这个问题,但最终还是没有一致的看法。我任性地选择了不包裹对象,直接传递数组的方式。其实到目前为止我也无法确定何种方式好,只是我个人更倾向于干净的数据罢了。

分页的情况

  包裹一层对象的目的主要是考虑到分页之类的情况会有额外数据。比如对一个列表分页,那么前端必须知道记录的总条数才可以计算出分页栏要显示的东西。于是响应的数据中就需要带上 count 之类的额外字段。这时候如果所有数据都包裹在一个对象中,那么就可以很容易地传输这些额外字段。甚至把 page、pagesize 之类的参数也一并传输,保持数据的完整性。
  以上方案确实已经可以方便地解决所有问题了。但也许是我对数据有洁癖吧?我更希望每个接口只做自己的事情。传输记录数量这种事情应该是另一个接口。也许在一般的 API 设计中将 count 放入另一个接口中请求才是正确的做法,但网络 API 的设计需要考虑的不仅仅是 API 的整洁,还得考虑 API 调用次数的开销。如果请求一个额外的接口来获取 count,再去调用数据接口显然多了一次网络请求,这样肯定不行。那么,我想要的整洁方案就真的无法实现了么?

解决方案

  其实我有准备了其它解决方案。我希望每个接口都能只做自己的事情。既然我们的问题是「调用两个接口的网络开销太大」,那么我们搞一个合并请求的接口不就完美解决了么?假设服务器上有数据 [{id:1},{id:2},{id:3}],那么可能有这些情况:
请求: /list
响应: [{"id":1},{"id":2},{"id":3}]
请求: /list/count
响应: {"count":3}
请求: /merge?args[]=%2Flist%2Fcount&args[]=%2Flist
响应: [{"count":3},[{"id":1},{"id":2},{"id":3}]]
  也许最后一个 merge 接口给人一种很怪异的关键,但我觉得这个逻辑是非常合理的。这么设计之后,每个 API 都只做自己的事情,没有任何僭越。

我的观点

  其实我觉得网络请求问题不该成为 API 设计的阻碍。这种问题是可以解决的,而且 SPDY 之后应该就不会再有这些问题了吧?

网名:
34.203.245.*
电子邮箱:
仅用于接收通知
提交 悄悄的告诉你,Ctrl+Enter 可以提交哦
神奇海螺
[查看全部主题]
各类Web技术问题讨论区
发起新主题
本模块采用即时聊天邮件通知的模式
让钛合金F5成为历史吧!
次碳酸钴的技术博客,文章原创,转载请保留原文链接 ^_^