Art4/json-api-client

Achieve compatability with JSON:API 1.1

Art4 opened this issue · 1 comments

Art4 commented

See #83 and #89

Art4 commented

Backward incompatibilities between 1.0 and 1.1

BC for JSON-API is defined in section 1 of the spec:

1.) Status

This page presents an archived copy of JSON:API version 1.0. None of the normative text on this page will change. While 1.0 is no longer the latest version of JSON:API, new versions will remain compatible with this one, as JSON:API uses a never remove, only add strategy.

Even if these two sentences seem to be mutually exclusive see this comment:

In the schema world, those two statements are mutually exclusive.

I get that, so I understand why they seem odd. But, in the protocol design world, this apparent "contradiction" is actually a logical prerequisite for extensibility. Please take a look at this great article if you have a second. Basically, it proves that you need to make the set of legally-producable messages smaller than the set of legally consumable messages (which is what additionalProperties: true does) if you want protocol extensibility. So this decision isn't some arbitrary quirk of the spec text or esoteric schema point: it's a critical part of the design!

There seems to be some BC breaks between 1.0 and 1.1. I will document them here so we can report them back and eventually find a way to handle them.

Allow extension member to be the only member in top-level document

PRs: json-api/json-api#1642

Changes between 1.0 and 1.1 (simplified)

  ### <a href="#document-top-level" id="document-top-level" class="headerlink"></a> Top Level

  A JSON object **MUST** be at the root of every JSON:API request and response
  document containing data. This object defines a document's "top level".

  A document **MUST** contain at least one of the following top-level members:

  * `data`: the document's "primary data".
  * `errors`: an array of [error objects](#errors).
  * `meta`: a [meta object][meta] that contains non-standard
    meta-information.
+ * a member defined by an applied [extension](#extensions).

Problem

The following content is valid 1.1, but is backward incompatible with 1.0 because data, errors and meta are missing:

POST /operations HTTP/1.1
Host: example.org
Content-Type: application/vnd.api+json;ext="https://jsonapi.org/ext/atomic"
Accept: application/vnd.api+json;ext="https://jsonapi.org/ext/atomic"

{
  "atomic:operations": [{
    "op": "add",
    "href": "/blogPosts",
    "data": {
      "type": "articles",
      "attributes": {
        "title": "JSON API paints my bikeshed!"
      }
    }
  }]
}

Allow extension member to be the only member in relationship object

PRs: json-api/json-api#1644

Changes between 1.0 and 1.1 (simplified)

  ##### <a href="#document-resource-object-relationships" id="document-resource-object-relationships" class="headerlink"></a> Relationships

  The value of the `relationships` key **MUST** be an object (a "relationships
  object"). Each member of a relationships object ("relationships") represents
  a "relationship" from the [resource object][resource objects]
  in which it has been defined to other resource objects.

  Relationships may be to-one or to-many.

  A relationship's name is given by its key. The value at that key **MUST** be an
  object ("relationship object").

  <a id="document-resource-object-relationships-relationship-object"></a>
  A "relationship object" **MUST** contain at least one of the following:

  * `links`: a [links object][links] containing at least one of the following:
    * `self`: a link for the relationship itself (a "relationship link"). This
      link allows the client to directly manipulate the relationship. For example,
      removing an `author` through an `article`'s relationship URL would disconnect
      the person from the `article` without deleting the `people` resource itself.
      When fetched successfully, this link returns the [linkage][resource linkage]
      for the related resources as its primary data.
      (See [Fetching Relationships](#fetching-relationships).)
    * `related`: a [related resource link]
    * a member defined by an applied [extension](#extensions).
  * `data`: [resource linkage]
  * `meta`: a [meta object][meta] that contains non-standard meta-information about the
    relationship.
+ * a member defined by an applied [extension](#extensions).

Problem

The following content is valid 1.1, but is backward incompatible with 1.0 because links, data and meta are missing:

POST /articles HTTP/1.1
Host: example.org
Content-Type: application/vnd.api+json;ext="https://example.org/ext/example"
Accept: application/vnd.api+json;ext="https://example.org/ext/example"

{
  "data": {
    "type": "articles",
    "attributes": {
      "title": "JSON API paints my bikeshed!"
    },
    "relationships": [
      {
        "example:color": {
          "name": "red",
        }
      }
    ]
  }
}

Allow extension member to be the only member in relationship links object

PRs: json-api/json-api#1644

Changes between 1.0 and 1.1 (simplified)

  ##### <a href="#document-resource-object-relationships" id="document-resource-object-relationships" class="headerlink"></a> Relationships

  The value of the `relationships` key **MUST** be an object (a "relationships
  object"). Each member of a relationships object ("relationships") represents
  a "relationship" from the [resource object][resource objects]
  in which it has been defined to other resource objects.

  Relationships may be to-one or to-many.

  A relationship's name is given by its key. The value at that key **MUST** be an
  object ("relationship object").

  <a id="document-resource-object-relationships-relationship-object"></a>
  A "relationship object" **MUST** contain at least one of the following:

  * `links`: a [links object][links] containing at least one of the following:
    * `self`: a link for the relationship itself (a "relationship link"). This
      link allows the client to directly manipulate the relationship. For example,
      removing an `author` through an `article`'s relationship URL would disconnect
      the person from the `article` without deleting the `people` resource itself.
      When fetched successfully, this link returns the [linkage][resource linkage]
      for the related resources as its primary data.
      (See [Fetching Relationships](#fetching-relationships).)
    * `related`: a [related resource link]
+    * a member defined by an applied [extension](#extensions).
  * `data`: [resource linkage]
  * `meta`: a [meta object][meta] that contains non-standard meta-information about the
    relationship.
  * a member defined by an applied [extension](#extensions).

Problem

The following content is valid 1.1, but is backward incompatible with 1.0 because self and related are missing:

POST /articles HTTP/1.1
Host: example.org
Content-Type: application/vnd.api+json;ext="https://example.org/ext/example"
Accept: application/vnd.api+json;ext="https://example.org/ext/example"

{
  "data": {
    "type": "articles",
    "attributes": {
      "title": "JSON API paints my bikeshed!"
    },
    "relationships": [
      {
        "links": [
          "example:link": {
            "href": "https://example.org",
          }
        ]
      }
    ]
  }
}