JSONAPI:更新包括属性的关系

时间:2018-05-29 03:02:45

标签: flask json-api marshmallow flask-restless jsonapiframework

我的SQLAlchemy表中有一个嵌套对象,使用Marshmallow's nested schema feature生成。例如,articles对象GET响应将包含author(一个User类型)对象。

我知道JSONAPI spec已经允许更新关系。但是,我经常想在一次调用中更新一篇文章及其嵌套对象(包含新作者的文章的POST请求将自动创建作者)。是否可以发出包含尚未存在的关系对象资源的PATCH请求?

所以不要只是这样:

PATCH /articles/1 HTTP/1.1
Content-Type: application/vnd.api+json
Accept: application/vnd.api+json

{
  "data": {
    "type": "articles",
    "id": "1",
    "relationships": {
      "author": {
        "data": { "type": "people", "id": "1" }
      }
    }
  }
}

如果不存在新作者,那么将其传递给新作者是理想的(这不是我的实际用例,但我有类似的现实生活需要):

PATCH /articles/1 HTTP/1.1
Content-Type: application/vnd.api+json
Accept: application/vnd.api+json
{
  "data": {
    "type": "articles",
    "id": "1",
    "relationships": {
      "author": {
        "data": { "type": "people", "id": "1", "attributes": {"name": "new author":, "articles_written": 1} }
      }
    }
  }
}

这是完全可能的,还是对REST框架可以支持的建议,还是完全违反JSON API规范?

1 个答案:

答案 0 :(得分:2)

使用JSON API规范v1.0无法一次更新多个资源。但有几个建议如何做到这一点。 official extensions not supported anymore都旨在支持一次创建,更新或删除多个请求。还有一个开放的拉取请求introduce operations to upcoming JSON API spec v1.2

例如,使用建议的操作[1]一次更新两个资源的请求将如下所示:

PATCH /bulk HTTP/1.1
Host: example.org
Content-Type: application/vnd.api+json

{
  "operations": [{
    "op": "update",
    "ref": {
      "type": "articles",
      "id": "1"
    },
    "data": {
      "type": "articles",
      "id": "1",
      "attributes": {
        "title": "Updated title of articles 1"
      }
    }
  }, {
    "op": "update",
    "ref": {
      "type": "people",
      "id": "2"
    },
    "data": {
      "type": "people",
      "id": "2",
      "attributes": {
        "name": "updated name of author 2"
      }
    }
  }]
}

这将在单个事务中更新title的{​​{1}} article属性1以及name资源person资源,其ID为2

更新一对一关系并在单一事务中更新相关资源的请求如下所示:

PATCH /bulk HTTP/1.1
Host: example.org
Content-Type: application/vnd.api+json

{
  "operations": [{
    "op": "update",
    "ref": {
      "type": "articles",
      "id": "1",
      "relationship": "author"
    },
    "data": {
      "type": "people",
      "id": "2"
    }
  }, {
    "op": "update",
    "ref": {
      "type": "people",
      "id": "2"
    },
    "data": {
      "type": "people",
      "id": "2",
      "attributes": {
        "name": "updated name of author 2"
      }
    }
  }]
}

这是一个请求,用于创建新的person并将其author关联到ID为article的现有1

PATCH /bulk HTTP/1.1
Host: example.org
Content-Type: application/vnd.api+json

{
  "operations": [{
    "op": "add",
    "ref": {
      "type": "people"
    },
    "data": {
      "type": "people",
      "lid": "a",
      "attributes": {
        "name": "name of new person"
      }
    }
  }, {
    "op": "update",
    "ref": {
      "type": "articles",
      "id": "1",
      "relationship": "author"
    },
    "data": {
      "type": "people",
      "lid": "a"
    }
  }]
}

请注意,订单很重要。必须由服务器按顺序执行操作。因此,必须先创建资源,然后才能将其与现有资源相关联。为了表达关系,我们使用本地ID(lid)。

请注意,只有在必须以交易方式执行请求时才应使用操作。如果每个包含的操作都可以原子方式执行,则应使用单个请求。

相对于implementation list provided on jsonapi.org,有一些库支持Patch扩展。

更新:操作未包含在JSON API v1.1的候选发布版中。它现在计划在v1.2。 pull请求的作者,也是规范的维护者之一,said“操作现在是最高优先级”。包含操作的v1.2的候选版本可能会在1.1最终版本的几个月内发布。“

[1]目前只建议向JSON API v1.2引入操作但不合并。可能会有重大变化。在实施之前阅读related pull request