摘自Fielding的文章(https://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven):
REST API永远不应具有对客户端重要的“类型化”资源。规范作者可以使用资源类型来描述接口背后的服务器实现,但是这些类型对于客户端而言必须是不相关且不可见的。对客户来说唯一重要的类型是当前代表的媒体类型和标准化的关系名称。 [同上]
在HYDRA中,可以在API文档中记录类,如下所示:
supportedClass:
'@id': 'schema:Event'
supportedProperty:
- property:
'@id': eventName
它不算是类型化资源吗? JSON-LD中甚至还有一个@type
字段。我了解标准化关系名称的重要性,因为它们为客户提供了使用资源或属性做有用的东西所必需的语义,格式和约束,但是通过限制API文档中可能关系的范围,我们实际上是在声明类型(类)。
没有类,客户将不知道会出现什么关系,而对客户进行编码以使其知道大多数关系类型(例如来自schema.org的信息)是不实际的。
此约束的确切含义是什么,在实践中有什么用? HYDRA不尊重这一约束吗?
我是出于理论兴趣而提出这个问题。实际上,我不在乎我的HTTP API是否满足所有约束条件。
答案 0 :(得分:1)
我认为我得到了“类型化资源”(正如Fielding所说的)与媒体类型(如JSON-LD / HYDRA)中定义的类型或类之间的区别。我正在回答自己的问题,但如有必要,请扩展/更正。
TL; DR 我的理解是,此约束将类型称为资源的预定义表示(或结构),并提倡记录可能的关系和媒体类型处理规则,而不是此结构。这些关系仍然可以归类为“类型”,但表示形式并不严格。
属性通常具有预定义的名称,并且在其封闭类型的上下文中可以理解。这意味着服务器/客户端应就此命名约定达成一致,以便处理这些类型,并且一种类型的名称与另一种类型的名称相同的字段可能具有完全不同的语义。它产生了刚性的资源结构。
另一方面,像JSON-LD这样的超媒体类型并不以通用方式使用属性。相反,他们使用一些嵌入式信息(@context)定义属性的语义,这些属性可以是其他实体,值对象,引用等。
通过处理具有给定超媒体类型的资源,这些属性将转换为一些定义明确的关系,通常在词汇表中进行定义。这意味着可以将相同的关系重新用于多种类型,例如name
和Person
中的Book
字段可以引用它们与值对象(例如简单的字符串名称)之间的https://schema.org/name关系。
这通过允许客户端使用公共词汇表用于关系类型以及通过定义媒体类型的处理规则来使客户端与服务器分离,因此建议在直接以其序列化格式使用资源之前对其进行预处理。您可能不知道如何返回。)
例如:
{
"@context": "http://schema.org/",
"@type": "Person",
"@id": "http://srv.org/users/1",
"name": "Jane Doe",
"telephone": "(425) 123-4567",
"url": "http://www.janedoe.com"
}
与
是同一资源{
"@context": {
"a": "http://schema.org/name",
"b": "http://schema.org/telephone",
"c": {
"@id": "http://schema.org/url",
"@type": "@id"
}
},
"@type": "http://schema.org/Person",
"@id": "http://srv.org/users/1",
"a": "Jane Doe",
"b": "(425) 123-4567",
"c": "http://www.janedoe.com"
}
甚至是
[
{
"@id": "http://srv.org/users/1",
"@type": [
"http://schema.org/Person"
],
"http://schema.org/name": [
{
"@value": "Jane Doe"
}
],
"http://schema.org/telephone": [
{
"@value": "(425) 123-4567"
}
],
"http://schema.org/url": [
{
"@id": "http://www.janedoe.com"
}
]
}
]