RESTful API设计 - 如何处理外键?

11

我正在设计一个RESTful API,想弄清楚如何显示和更新资源的外键。

假设我有一个User对象,它有一个id、名称和一个指向实体Computer的外键(多对一关系)。

在大多数在线示例中,我看到的是:

GET /users/1

{
  id: 1,
  name: "Bob",  
  computer: "<url>/computers/5"
}

我能理解,这是一个指向另一个资源的链接。但如果您想为Bob选择另一台计算机,该怎么办呢?

PUT /users/1

{
  name: "Bob",
  computer: "<url>/computers/4"
}

感觉很奇怪。我还在考虑以下情况:假设实现API的人可以使用下拉框为Bob选择计算机,并应该选择当前计算机,我需要id来完成这个操作。我需要自己解析URL来去掉id吗?

有没有不这样做的原因:

GET /users/1

{
  id: 1,
  name: "Bob",  
  computerId: 5
}

PUT /users/1

{
  name: "Bob",
  computerId: 4
}
3个回答

4
我会尝试对HATEOAS进行一些规范化,具体做法如下:

获取用户信息:GET /users/1


该接口用于获取ID为1的用户信息。
{
  links: [
    { rel: "computer", href: "/users/1/computers/5" },
  ],
  user: {
    id: 1,
    name: "Bob",
    computer: 5,
  }
}

PUT /users/1

{
  name: "Bob",
  computer: 4,
}

GET /users/1

{
  links: [
    { rel: "computer", href: "/users/1/computers/4" },
  ],
  user: {
    id: 1,
    name: "Bob",
    computer: 4,
  }
}

链接URL显然可以是/computers/n,如果这是您的首选。
这样做可以使您的表示始终只是数据,并且GET请求的主体提供应用程序可以使用的URL。 这样,如果您更改URL层次结构(即从/computers/n更改为/users/m/computers/n)),则无需更改手动构建URL的任何客户端代码。

感谢您的回答。我认为这是最清晰、最易于操作的方式,尽管它可能并没有完全遵循HATEOAS原则。 - Geoffrey De Vylder

3

通过GET方法,您需要使用链接来满足HATEOAS约束。

{
  id: 1,
  name: "Bob",  
  computer: {uri: "<url>/computers/5"}
}

通过使用PUT方法,您可以使用ID进行操作。

{
  name: "Bob",
  computer: {id: 4}
}

这个想法是URL(或URL模板)必须由服务器生成。因此,客户端无需知道如何构建URL,这使得服务+客户端代码DRY,或者用其他术语来说,它放松了客户端和服务实现之间的耦合。
(您可以使用标准(或草案)解决方案来描述超链接。例如:ATOM,XLink,RDF + Hydra,HAL等)

谢谢。我喜欢这种方法,但我不喜欢在GET和PUT中使用不同的标识符。 - Geoffrey De Vylder
@geoffreydv 这是因为URI是供客户端跟随的,而id是供服务器处理的。如果您愿意,可以在PUT中发送URI而不是id,但这并没有任何优势。您可以将id和其他属性添加到GET响应中,因此不必仅使用单个获取URI。通常我们会提供一些属性,客户端可以根据需要跟随URI进行详细说明。 - inf3rno

1
如果你真的采用HATEOAS,你应该只使用URI作为标识符,而不是id字段。我建议完全删除它。当然,在你的应用程序中,你需要解析载荷中的URI -- 你已经有了解析器,显然 -- 但这比要求客户端来做更好。
如果你或你的客户端在载荷中发送除URI之外的id字段,或者如果你要求客户端解析URI并确定语义,那么你就打败了使用HATEOAS的目的,因为客户端实现将与该语义耦合。最好的方法是将URI作为驱动与客户端交互的唯一标识符。

谢谢你的回答。出于某些原因,我仍然觉得完全遵循HATEOAS原则虽然使一些事情更容易,但也会使其他事情更加复杂。 - Geoffrey De Vylder
1
REST的目的是为了长期使事情更容易和更有效率。许多限制直接与短期简单性和效率相对立。如果做得正确,它肯定会使设计阶段更加复杂。如果您没有实际的长期要求,您不需要严格遵守这些原则。 - Pedro Werneck

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