json 模式链接数组中表示项目的片段是什么

What is the fragment that represent an item in a json schema links array

给定以下两个 JSON 模式定义

架构 A

{
  "$schema": "http://json-schema.org/draft-04/hyper-schema",
  "title": "Member Resource",
  "description": "A Member at a group",
  "id": "schemata/member",
  "definitions": {
    "first_name": {
      "description": "the first name",
      "example": "Severus",
      "minLength": 1,
      "maxLength": 255,
      "type": "string"
    },
    "last_name": {
      "description": "the last name",
      "example": "Snape",
      "minLength": 1,
      "maxLength": 255,
      "type": "string"
    },
    "member_response": {
      "description": "Successful response to a show or search request",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "member": { "$ref": "/schemata/member" }
      },
      "required": ["member"]
    },
    "error_response": {
      "description": "Error response to a show or search request",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "reference_id": {"$ref": "#/definitions/reference_id"},
        "errors": {"$ref": "#/definitions/errors"}
      },
      "required": [errors"]
    }
  },
  "links": [
    {
      "description": "Retrieve a member",
      "href": "/members/{(%23%2Fschemata%member%2Fdefinitions%2Fidentity)}",
      "method": "GET",
      "rel": "instance",
      "title": "Show",
      "targetSchema": {
         "description": "Result of a get request. Can be either a success or a failure.",
         "type": ["object"],
         "oneOf": [
           { "$ref": "#/definitions/member_response" },
           { "$ref": "#/definitions/error_response" }
         ]
      }
    },
    {
      "description": "Search for a member",
      "href": "/members/search",
      "method": "GET",
      "rel": "instance",
      "schema": {
        "description": "The expected payload for a search request",
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "first_name": {
            "$ref": "#/definitions/first_name"
          },
          "last_name": {
            "$ref": "#/definitions/last_name"
          }
        },
        "required": ["first_name", "last_name"]
      },
      "targetSchema": {
         "description": "Result of a get request. Can be either a success or a failure.",
         "type": ["object"],
         "oneOf": [
           { "$ref": "#/definitions/member_response" },
           { "$ref": "#/definitions/error_response" }
         ]
      }
      "title": "Search"
    }
  ],
}

架构 B

{
  "$schema": "http://json-schema.org/draft-04/hyper-schema",
  "title": "Member Resource",
  "description": "A Member at a group",
  "id": "schemata/member",
  "definitions": {
    "first_name": {
      "description": "the first name",
      "example": "Severus",
      "minLength": 1,
      "maxLength": 255,
      "type": "string"
    },
    "last_name": {
      "description": "the last name",
      "example": "Snape",
      "minLength": 1,
      "maxLength": 255,
      "type": "string"
    },
    "search_payload": {
      "description": "The expected payload for a search request",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "first_name": {
          "$ref": "#/definitions/first_name"
        },
        "last_name": {
          "$ref": "#/definitions/last_name"
        }
      },
      "required": ["first_name", "last_name"]
    },
    "member_response": {
      "description": "Successful response to a show or search request",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "member": { "$ref": "/schemata/member" }
      },
      "required": ["member"]
    },
    "error_response": {
      "description": "Error response to a show or search request",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "reference_id": {"$ref": "#/definitions/reference_id"},
        "errors": {"$ref": "#/definitions/errors"}
      },
      "required": [errors"]
    },
    "get_response": {
      "description": "Result of a get request. Can be either a success or a failure.",
      "type": ["object"],
      "oneOf": [
        { "$ref": "#/definitions/member_response" },
        { "$ref": "#/definitions/error_response" }
      ]
    }
  },
  "links": [
    {
      "description": "Retrieve a member",
      "href": "/members/{(%23%2Fschemata%member%2Fdefinitions%2Fidentity)}",
      "method": "GET",
      "rel": "instance",
      "title": "Show",
      "targetSchema": {
        "$ref": "#/definitions/get_response"
      }
    },
    {
      "description": "Search for a member",
      "href": "/members/search",
      "method": "GET",
      "rel": "instance",
      "schema": {
        "$ref": "#/definitions/search_payload"
      },
      "targetSchema": {
        "$ref": "#/definitions/get_response"
      },
      "title": "Search"
    }
  ],
}

两种模式在功能上是相同的。不同之处在于 targetSchema 在模式 A 中内联定义,但在模式 B.

中定义为引用

我使用一个库来验证 API 端点的输入和输出。例如,在测试我的 APIs 时,我想验证对每个请求的响应 returns 一个符合 API 的 targetSchema 的 JSON 对象。

JSON::Validator.fully_validate(
  schema,
  object_to_test,
  :fragment => "/path/to/fragment"
)

为了针对上面定义的 /members/search API 根据 targetSchema 进行验证,我需要能够引用它的 targetSchema.

在架构中 B 我可以做到

JSON::Validator.fully_validate(
  schema,
  object_to_test,
  :fragment => "#/definitions/get_response"
)

是否也可以对架构 A 执行上述操作?即我可以直接引用搜索 link 的实际 targetSchema 吗?也许它看起来像下面的样子

JSON::Validator.fully_validate(
  schema,
  object_to_test,
  :fragment => "#/links[1]/targetSchema"
)

JSON::Validator.fully_validate(
  schema,
  object_to_test,
  :fragment => "#/links/[SOME_WAY_OF_SPECIFYING_THAT_TITLA_EQL_SEARCH"]/targetSchema"
)

根据您的架构,您可以使用以下 JSON 指针 (1) 引用搜索 link 的 targetSchema

#/links/1/targetSchema

这里 1 是 links 数组中所需项目的索引。这是引用数组中项目的唯一方法。要准确回答这个问题——无法指定数组中 title 等于“搜索”的项目。

显然,使用索引引用 targetSchema 是很脆弱的。如果您在错误的位置将 link 添加到架构中,您的代码将会中断。如果您循环遍历代码中的 link 并选择您需要的那个,您会过得更好。

您可能会问,“为什么引用 link 的 targetSchema 进行验证如此困难?”答案是 targetSchema 不用于验证。 targetSchema 仅供参考。这是文档。响应应负责遵守的唯一模式是它在 response(2) 中声明的模式。这是REST的核心思想之一。客户端和服务器是解耦的。客户端不会对其将获得的响应做出任何假设。响应本身应该包含解释响应所需的所有信息以及您接下来可以做什么。

  1. https://www.rfc-editor.org/rfc/rfc6901
  2. http://json-schema.org/latest/json-schema-core.html#anchor33