API 设计:使数据具有人类可读性与强制更多 API 调用 [关闭]

Posted

技术标签:

【中文标题】API 设计:使数据具有人类可读性与强制更多 API 调用 [关闭]【英文标题】:API Design: Making data human readable vs forcing more API calls [closed] 【发布时间】:2022-01-01 22:39:03 【问题描述】:

假设我们的数据库中有一个Product 表。这代表存在的产品:

productId brandId (FK) name description capacity pricePerNight
1 2 Tent This is a tent 4 20

假设我们的数据库中还有一个Brand 表。这代表品牌并通过 FK 链接到 Product 表:

id name
1 Vango
2 Quechua

现在假设我正在制作一个允许客户查询所有产品的公共 API。我希望客户能够(方便地)看到每种产品的品牌名称。

我的选择是:(a) 当他们 GET /product 返回带有新的人类可读字段 (brand) 的 Product 对象的编辑版本时,除了/替换 FK:


        "productId": 1,
        "brand": "Quechua",
        "name": "Tent",
        "description": "This is a tent",
        "capacity": 4,

(b) 返回数据库中存在的Product 对象,从而迫使客户在想要访问品牌名称时进行两次调用(例如,一次调用GET /product,一次调用GET /brand):


        "productId": 1,
        "brandId": 2,
        "name": "Tent",
        "description": "This is a tent",
        "capacity": 4,

我经常遇到这种情况,我想知道 RESTful API 的最佳实践是什么。非常欢迎任何意见。

编辑:IRL 我正在构建一个公共 API,它需要对我们公司的集成合作伙伴尽可能直观且易于使用。

【问题讨论】:

【参考方案1】:

表之间有关系,所以你不需要调用两个 API。 在上述情况下,我通常的做法是调用一个 api,即 /product 并返回产品对象,并且产品对象内部也包含品牌对象。 这种方法在 springboot(Java) 和 Laravel(php) 等知名框架内部也广泛使用。


        "productId": 1,
        "name": "Tent",
        "description": "This is a tent",
        "capacity": 4
         "brand":
           "id":1,
           "name":"brandName"
        

【讨论】:

【参考方案2】:

我经常遇到这种情况,我想知道 RESTful API 的最佳实践是什么。非常欢迎任何意见。

启发式:您将如何在网络上进行操作?

对于网页,通常只有一个页面组合了您需要的所有信息,即使这些数据分布在多个表中。

URI 的拼写通常不是来自表格,而是通过考虑此报告的名称,并选择具有相似语义同时与您的本地拼写约定保持一致的标识符。

在这里,我们似乎有某种形式的“产品目录”或“库存清单”,所以这个概念很可能就是我们在 URI 中表达的内容。

(注意:REST API 的部分意义在于它充当外观,隐藏底层实现细节。您不应该觉得有义务在标识符中公开表名。)

【讨论】:

【参考方案3】:

从 DB 层开始,您可以使用 只读视图 来读取数据。此视图可以组合跨不同表的字段(例如示例中的外键关系)。

此外,如前所述,您的响应可能包括您查询的实体所引用的对象。

归根结底,几乎没有人直接从 API 消费数据;通常,两者之间有一些前端基础设施。因此,您需要在拥有足够精简的响应负载和尽量让客户端发出尽可能少的请求之间取得平衡。

PS:这个Stack Exchange thread 可能是相关的。

【讨论】:

【参考方案4】:

我能给出的最佳答案是“让客户指定它想要的数据”,例如通过使用GraphQL。

这个问题类似于 ORM 框架面临的挑战——我是否加载整个依赖关系图(例如,“品牌”属于一个类别,一个类别有一个经理,一个经理有一个部门,一个部门有一个...... )。

GraphQL 改变了这种动态 - 它让 API 客户端指定它想要的数据。

替代方案是“加载一级依赖”(类似于Danish's answer),尽管这很快意味着客户端必须了解您的数据库架构 - 这会在客户端和 API 服务器之间建立紧密耦合。

【讨论】:

以上是关于API 设计:使数据具有人类可读性与强制更多 API 调用 [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

笔记:泛型

使用PreparedStatement接口操作数据库

PHP 使字节化人类可读

人类可读的 GUID

Java8基础知识泛型

AngularJS Resource:与 RESTful API 交互