我正在设计一个RESTful API,而我正试图弄清楚如何显示和更新资源的外键。
让我有一个对象User,它有一个id,name和一个外键(多对一关系)到实体:Computer。
我在大多数在线示例中看到的内容:
GET / users / 1
{
id: 1,
name: "Bob",
computer: "<url>/computers/5"
}
我可以理解,它是指向其他资源的链接。但是当你想为鲍勃选择另一台计算机时你会怎么做?
PUT / users / 1
{
name: "Bob",
computer: "<url>/computers/4"
}
这感觉很奇怪。 我还在考虑以下情况:假设必须实现API的人可以使用下拉列表为Bob选择计算机,并且应该选择当前的计算机,我需要id来执行此操作。我是否必须自己解析网址以切断ID?
我不应该这样做:
GET / users / 1
{
id: 1,
name: "Bob",
computerId: 5
}
PUT / users / 1
{
name: "Bob",
computerId: 4
}
答案 0 :(得分:3)
我很想在这里将HATEOAS正式化,并且:
{
links: [
{ rel: "computer", href: "/users/1/computers/5" },
],
user: {
id: 1,
name: "Bob",
computer: 5,
}
}
{
name: "Bob",
computer: 4,
}
{
links: [
{ rel: "computer", href: "/users/1/computers/4" },
],
user: {
id: 1,
name: "Bob",
computer: 4,
}
}
如果您愿意,链接网址显然可以是/computers/n
。
这使您的表示始终只是数据,并且GET的主体可以提供应用程序可以使用的URL。这样,如果您更改了网址层次结构(即从/computers/n
更改为/users/m/computers/n)
,则无需更改任何手动构建网址的客户端代码。
答案 1 :(得分:2)
通过GET,你必须使用链接来满足HATEOAS约束。
{
id: 1,
name: "Bob",
computer: {uri: "<url>/computers/5"}
}
通过PUT你可以使用id
{
name: "Bob",
computer: {id: 4}
}
关于这一点的想法,URI(或URI模板)必须由服务器生成。因此,客户端不必知道如何构建URI,这使得服务+客户端代码DRY,或者换句话说它放松了客户端和服务实现之间的耦合。
(您可以使用标准(或草稿)解决方案而不是自定义解决方案来描述超链接。例如:ATOM,XLink,RDF + Hydra,HAL等。)
答案 2 :(得分:1)
如果你真的拥抱HATEOAS,你应该只使用URI。 URI是您的标识符,而不是id
字段。我会完全删除它。当然,在您的应用程序中,您必须解析有效负载中的URI - 显然您已经拥有了解析器 - 但是这样做比要求客户端更好。< / p>
如果您或您的客户端在有效负载中发送URI以外的id字段,或者您要求客户端解析URI并找出语义,那么您将失去使用HATEOAS的目的,客户端实现将耦合到该语义。最好的办法是将URI作为您用来推动与客户互动的唯一标识符。