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

时间:2015-11-26 12:24:55

标签: rest

我正在设计一个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
}

3 个答案:

答案 0 :(得分:3)

我很想在这里将HATEOAS正式化,并且:

GET / users / 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,
  }
}

如果您愿意,链接网址显然可以是/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作为您用来推动与客户互动的唯一标识符。