REST API建模中的继承和多态性

21

我有一个对象层次结构,想要通过REST API公开,并讨论最佳实践。我之前看到过这个问题(例如这里的结尾这里这里,特别是这里),但从未得出任何结论。

假设我有一个基类,比如Animal,以及许多不同的继承类,比如AntelopeBird、...、Zebra。每种动物都具有独特的属性。

哪个更好呢?

  1. 一个端点路径:/animals。您根据种类发送和接收略有不同的主体。有一个type字段可帮助解析。
  2. 每种动物都有一个单独的端点路径,/animals/antelopes/animals/birds、...、/animals/zebras。每个端点始终接受和返回一个一致的主体(但这些主体彼此不同)。
2个回答

8
我会选择选项1。原因是:如果您的列表-羚羊,鸟类,...,斑马在未来增加,那么您将不得不为每种动物创建单独的端点。
假设是/animals/antelopes/animals/birds的有效负载之间没有太大的区别。如果差异更大,则需要为每个有效负载创建单独的端点。 如果有效负载之间有较小的差异,我建议添加额外的映射,其中包含键值对,这些键值对是特定于该特定动物类型的值。
正如您所提到的,额外的映射可以是以下类型-
{
 'shared_animal_attribute_1': 'foo', 
 'shared_animal_attribute_n': 'bar', 
 'extra_attributes': 
     { 
         'antelopiness': 10
     }
}

你需要在服务器端添加额外的处理逻辑来处理这些属性。这将减轻维护单独端点的痛苦。如果你有模式验证,实现起来就很方便。

嗯,@asg,我不确定它看起来像负载和响应对于每个动物都是相同的。实际上它们是不同的——“您发送和接收略有不同的主体,具体取决于种类”和“每种动物都有独特的属性”。我同意,如果每种动物都有相同的负载和响应,(1)将是显而易见的选择。这里棘手的问题是它们是不同的。 - emft
嘿@emft,这是你在问题#2中提到的内容:“每个端点的有效载荷和响应都相同”。如果是相同的,那么为什么需要单独的端点呢?这就是重点。 - asg
嘿@asg,我很想给你点赞 - 你能否稍微修改一下你的答案以反映我们的对话,然后我就可以接受它了?谢谢! - emft
@emft 当然,我会做的:)谢谢你的提醒! - asg
在我看来,REST API 中的多态性是一种反模式。 - Finster
显示剩余6条评论

6

OpenAPI 3.0(前身为Swagger)具有真正的JSON多态支持。

自JSON schema v1.0以来,已经可以使用oneOf、allOf、anyOf等关键词组合模式,并验证消息载荷。

https://spacetelescope.github.io/understanding-json-schema/reference/combining.html

然而,在Swagger中,通过关键词discriminator(v2.0+)和oneOf(v3.0+)增强了模式组成,以支持继承和多态性。

https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#schemaComposition

我在这里提供了一个多态POST方法的示例。


确实,OAS允许这样做。然而,在Swagger UI中没有支持该功能的显示(链接),如果您无法向任何人展示该功能,则我认为该功能的用途有限。 - emft
2
@emft,不是这样的。在撰写本答案时,Swagger UI已经支持了该功能。 - Andrejs Cainikovs
同时,服务器代码无法处理“oneOf”模式。它会变成“Object”。 - PeiSong
2
OAS 支持此功能,但似乎代码生成器不支持 https://github.com/OpenAPITools/openapi-generator/issues/15 - DarVar
对于Java,似乎已经通过OpenAPITools PR#5120(https://github.com/OpenAPITools/openapi-generator/pull/5120)固定了。 - dbaltor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接