为 RESTful API 选择数据类型

我们的工程团队正在完善一个新的 RESTful API,您可以使用它来构建自己的应用程序并将 Phone.com 功能整合到您的业务系统中。

我们从未质疑过我们是否会使用 REST——几乎可以肯定的是,REST 是构建 API 的最佳方式。几乎一致认为 RESTful API 应该基于 JSON。但由于 REST 是一组体系结构指南,而不是协议或规范,我们必须在一开始就决定使用哪种媒体类型进行输出。也就是说,我们将使用哪种 JSON 结构来传达我们的数据。

没有广泛认同的 RESTful 数据结构方式,这导致我们对不少于六种不同的提议标准进行了冗长的分析!我们想分享一些关于我们的研究和我们所做的决定的信息。

我们在寻找什么

我们最初的目标非常简单:

  1. 避免从头开发我们自己的格式。这个世界不需要另一种 JSON REST 媒体类型!
  2. 选择一种简单易懂且易于开发者理解的类型,同时涵盖我们的需求和用例。

我们发现了令人眼花缭乱的多种选择:HAL,JSON-LD, 警报器,JSON API,Collection+JSON 和 Mason 都引起了我们的注意,虽然我没有时间给出详细的结构比较,但我确实想回顾一下每一个并提供我们的评论。

HAL(超文本应用语言)

所有 JSON REST 格式的鼻祖,HAL 于 2011 年首次提出. 这是一个轻量级规范,主要侧重于 API 资源之间的链接。

我们喜欢 HAL 的简单性。不幸的是,对于我们的目的而言,它简单了。HAL 不支持表单——仅支持链接——并且不支持错误处理等高级主题。然而,我们确实喜欢它如何提供嵌入式资源和具有相同关系的多个链接。

JSON-LD(关联数据的 JSON)

这是另一种早期的轻量级格式。JSON-LD 主要用于将链接结构反向移植到现有的 JSON API 上。它的核心也不支持高级要求,尽管有一种名为 Hydra,它试图解决这个弱点。

由于我们的 API 是全新的,因此我们不需要 JSON-LD 的主要用例,即改造现有的 JSON API。所以我们一直在寻找。

警报器

较新的 JSON 媒体类型是 Siren。虽然我们赞赏它对表单的处理,但 Siren 没有错误处理并且对复杂的 POST 或 PUT 请求的支持不足。此外,我们发现它在 class 属性中定义媒体子类型的概念很笨拙且不发达,我们不喜欢它更严格的数据结构,这需要将数据封装在 properties 对象。

JSON API

沿着严格规范的趋势走得最远的是 JSON API。在我们考虑的所有媒体类型中,它的规格最长、最详细。它甚至定义了必须返回哪些 HTTP 状态代码,以及必须如何处理输入参数。对于那些愿意将几乎所有界面设计决策都交给规范的人来说,没有比这更好的了。

但是,Phone.com API 的需求在几个方面都很复杂,我们不相信 JSON API 可以在不违反规范的情况下处理 100% 的需求——与规范有重大偏差的实现比完全没有规格。

此外,我们认为 JSON API 将对象合并到其包含的数组中的方式可能适合那些希望严重依赖缓存数据的客户,但它确实会使数据结构复杂化,并且很难看到其中的内容。虽然在客户端应用程序完成后这不是问题,但 API 的可用性在编写客户端的过程中最相关,而不是之后。开发人员必须能够快速轻松地理解其中的内容,以便首先编写客户端。

集合+JSON

我们发现 Collection+JSON(现已合并到名为 Collection.Dot+JSON)的变体非常适合大量使用列表的 API,这当然适用到 Phone.com API。我们也很感激它能处理我们的一些高级用例,而不仅仅是链接。然而,Collection+JSON 强加了一个严格的数据结构,要求一切被构造为一个列表,甚至是表示单个对象的 API 端点。

梅森

最后但绝非最不重要的一点是,我们探索了 Mason——具体来说,草案 2。虽然在 JSON REST API 社区中相对不为人知,但我们发现它是一个非常强大的选项,可以灵活地处理我们的各种用例。Mason 有错误处理和复杂表单支持的规范。它还包括 multipart/form-data 请求的规范,这对于 JSON 媒体类型来说很少见。

对于表单,除了模板化 URL 之外,Mason 还包括对 JSON-Schema 的明确支持,使其非常灵活。通过允许人类可读的标题和描述,它也对开发人员更加友好,可以通过特殊的请求标头在生产中将其关闭。

Draft 2 还结合了带有链接和表单的创新理念。几乎所有其他媒体类型都将表单和链接拆分到单独的列表中,但 Mason 将它们组合到一个单独的 @controls 属性中。这导致更简单的数据结构和更自然的分组,API 客户端可能为给定资源提供的所有不同选项。

总的来说,我们发现 Mason 有很多值得喜欢的地方!我们发现的唯一真正的缺点是开发人员缺乏意识。它只存在了几年。

确定 JSON 类型

在我们对每种媒体类型进行第一次审查后,我们开始欣赏那些关注高级用例的媒体类型,例如错误处理和表单。我们最初倾向于使用 Collection+JSON,但我们对数据结构刚性和非列表数据的笨拙处理的担忧促使我们转向其他地方。我们最终爱上了 Mason草案 2。我们认为它在稳健性和开发人员友好性之间取得了最佳平衡。

实施后

我们决定使用 Mason 数据类型已经三个月了。在此期间,我们编写了三个不同的 Mason API,而不是一个,我们非常高兴!

为了您的参考,我们开源了两个 PHP 库来帮助完成此类任务。请随时检查它们!

  • Mason-PHP
  • Mason-Laravel

我们很想听听您对为您的 API 项目选择 JSON 数据类型的想法。是什么促使您选择上述类型之一,或者我没有提到的另一种数据类型?