Json-LD中的主细节表示

时间:2014-08-17 16:50:00

标签: rest restful-architecture json-ld hypermedia hydra-core

on forhand:抱歉,如果我误解了超媒体或Restfull概念:这是一项正在进行的工作......)

我试图弄清楚超媒体和水印(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中检索到的文件或者我是否错过了什么?


然后更进一步,我已经声明产品是一个水印:链接,以便客户端可以通过HTTP GET跟踪该链接(与之交互)并检索产品列表。这将是一个这样的列表:

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

此处客户端收到产品列表(可能是分页集合)。但是,如果客户希望将其显示给用户,请说明一个 [产品ID,价格,名称] (不是所有产品属性)的表格

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

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

问候

2 个答案:

答案 0 :(得分:4)

有点晚了,但我会尽力回答你的问题塞德里克。

  

说我在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)将操作附加到属性(productscustomers)。

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

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

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

...
"@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以除去它,而不是专门处理它们。

答案 1 :(得分:2)

注意:Hydra部分答案我不太确定,我认为JSON-LD和REST是可以的。

您可以使用@base和JSON-LD的相对IRI,或者您可以在@context中定义名称空间,之后您可以将相对IRI用作ns:relativeIRI。每一个都比返回完整的IRI更好。 (使用客户端的通用JSON-LD解析器而不是简单的JSON解析器更容易解析结果。)

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

{
    "@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添加新的supportedOperation作为method: GET。我想获取操作是针对具有用户输入的搜索,但如果您不想为每个链接添加新属性,我认为您没有其他选择。

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

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