3

预先准备:对不起,如果我误解了超媒体或 Restfull 概念:这是一项正在进行的工作......)

我试图弄清楚超媒体和 hydra ( http://www.markus-lanthaler.com/hydra ),并且在设计我的 api 之前有一些关于向客户端返回信息的问题。

假设我有一个位于 www.myshop.com 的网上商店

到根的 HTTP GET 可以返回(例如)表示为链接的资源列表(在 json-ld 文档中):

...
"@id": "/api",
"products" : "www.myshop.com/api/products",
"customers":"www.myshop.com/api/customers"
...

关于 hydra 的第一个问题,我如何在此处添加操作?似乎客户端需要在加载应用程序之前加载另一个文档。我的意思是潜在的行动不在从 www.myshop.com/api 检索到的文档中或者我错过了什么?


然后更进一步,我已经声明products是一个 hydra:Link 以便客户端可以使用 HTTP GET 跟随该链接(与其交互)并检索产品列表。这将是一个这样的列表:

....
{
  "@id": "/api/products/123",
  "@type": "vocab:Product"
},
{
  "@id": "/api/products/124",
  "@type": "vocab:Product"
},
....

在这里,客户收到一个产品列表(这可能是一个分页集合)。但是如果客户想要向用户展示它,假设一个带有[产品 ID、价格、名称]的表格(不是所有产品的属性)

第二个问题:如果没有客户端向服务器发送每个产品的请求,但仍然提供获取产品详细信息的链接,我怎么能做到这一点,(或者甚至这里有四个链接:一个用于获取详细信息,一个用于删除,一个用于与朋友分享,最后一个用于将其添加到篮子)?

事实上,如果文档本身没有链接,我很难弄清楚 hydra 是如何发挥作用的?我认为 Hal 使用这种方法在文档本身中添加链接(如果我是对的),我试图找出 hydra 是如何做这个链接的......

问候

4

2 回答 2

4

有点晚了,但我还是会尝试回答你的问题 Cedric。

假设我有一个位于 www.myshop.com 的网上商店

到根的 HTTP GET 可以返回(例如)表示为链接的资源列表(在 json-ld 文档中):

 ... "@id": "/api",
 "products" : "www.myshop.com/api/products",
 "customers":"www.myshop.com/api/customers" ...

关于 hydra 的第一个问题,我如何在此处添加操作?似乎客户端需要在加载应用程序之前加载另一个文档。我的意思是潜在的行动不在从 www.myshop.com/api 检索到的文档中或者我错过了什么?

您在这里基本上有两个选择:1) 将操作直接嵌入响应中,或者 2) 将操作附加到属性 ( products, customers) 中。

方法 1) 看起来有点像这样:

...
"@id": "/api",
"products" : {
  "@id": "http://www.myshop.com/api/products",
  "operation": {
    "@type": "Operation",
    "method": "POST",
    "expects": "Product"
  }
}
...

虽然方法 2) 会将相同的操作附加到products引用的 Hydra ApiDocumentation 中的属性:

...
"@id": "...products",
"supportedOperation": {
  "@type": "Operation",
  "method": "POST",
  "expects": "Product"
}
...

请注意,在 1)中我使用operation了,而在 2)中我使用了supportedOperation. 此外,您应该使用比Operation.

关于你的第二个问题:

使用 HTTP GET 并检索产品列表。这将是一个这样的列表:

....
{
  "@id": "/api/products/123",
  "@type": "vocab:Product"
},
{
  "@id": "/api/products/124",
  "@type": "vocab:Product"
},
....

在这里,客户收到一个产品列表(这可能是一个分页集合)。但是如果客户想要向用户展示它,假设一个带有 [产品 ID、价格、名称] 的表格(不是所有产品的属性)

第二个问题:如果没有客户端为每个产品向服务器发送请求,但仍然提供获取产品详细信息的链接,我怎么能做到这一点,(甚至这里有四个链接:一个用于获取详细信息,一个用于删除,一个用于与朋友分享,最后一个用于将其添加到篮子)?

您可以直接在集合中添加尽可能多的信息(包括链接)。

....
{
  "@id": "/api/products/123",
  "@type": "vocab:Product",
  "name": "Product 123",
  "price": "9.99"
},
{
  "@id": "/api/products/124",
  "@type": "vocab:Product",
  "name": "Product 124",
  "price": "19.99"
},
....

这样,如果集合不包含所需的信息,客户端只需要取消引用项目。

事实上,如果文档本身没有链接,我很难弄清楚 hydra 是如何发挥作用的?

当然,您在文档中也有链接。链接只是其值恰好是 URL 的属性(具有@id属性的对象,除非您在上下文中将属性的类型设置为@id以摆脱它),而不是对它们进行特殊处理。

于 2014-09-16T14:52:08.390 回答
2

注意:我不太确定答案的 Hydra 部分,我认为 JSON-LD 和 REST 没问题。

您可以@base通过 JSON-LD 使用和相对 IRI,也可以@contextns:relativeIRI. 每一个都比返回完整的 IRI 要好。(在客户端使用通用 JSON-LD 解析器比简单的 JSON 解析器更容易解析结果。)

@vocab您可以使用 Hydra 词汇定义自己的,也可以在@context. 如果你想“添加动作”,你必须hydra:Operation在你的词汇中使用子类。像这样的东西(但我不是九头蛇专家):

{
    "@id": "vocab:ProductList",
    //...
    "hydra:supportedOperations": [
        {
            "@type": "hydra:CreateResourceOperation",
            "method": "POST",
            "expects": "vocab:Product"
        }
        //...
    ]
}

一般来说,通过 REST,如果您需要具有较少属性的相同资源,那么您必须为该资源添加一个新的 IRI,例如:/myresource?fewer=1. 例如在你的情况下:/api/products/?fields="id, price, name"没关系。

如果您想要多个链接,Hydra 有 2 个选择;您可以添加一个新hydra:Link的作为属性,或者您可以添加一个新hydra:Operation的作为supportedOperationwith method: GET。我猜 get 操作是针对具有用户输入的搜索之类的,但是如果您不想为每个链接添加新属性,我认为您别无选择。

实际上 Hydra 确实有链接和操作支持。也许不清楚,但 JSON-LD 是一种 RDF 格式,您可以在其中定义 RDF 三元组。因此,您使用的 IRI"customers":"www.myshop.com/api/customers"只是资源标识符而不是链接。一个链接应该有 IRI、标题、方法(GET)、语言、内容类型、iana:relation 等等……所以不可能用一个 IRI(资源标识符)来描述一个你可以跟随的链接。通过处理 REST 资源,客户端永远不应该检查 IRI 结构以了解如何显示它从您那里获得的信息。您必须检查链接的其他属性,尤其是iana:relations或 Hydra 可能的操作类型才能做到这一点。所以例如在你的情况下www.myshop.com/api/dav8ufg723udvbquacvd723fudvg是客户列表的完全有效的 IRI。我们使用漂亮的 IRI 只是因为在服务器端更容易配置生成它们,并为它们配置路由器。

在进一步的问题之前,请检查Hydra 词汇。正如你所看到的,一个Class可以拥有supportedOperationssupportedProperties这两个都是集合。ALink是一个Property子类,可以有一个Operation. 通过集合,我认为您必须使用包含集合项目的Collectionmember......请注意,通过 JSON-LD,定义单个项目或具有相同类型的多个项目没有区别。在上下文中,您必须只定义类型,并且属性的值可以包含单个项目或项目数组...如果您想要一些约束,我想您必须添加一些 OWL 三元组,以及使用它们检查值的验证器。

于 2014-08-23T10:14:28.967 回答