Skip to content

Profile extensions #957

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 23 commits into from
Closed
Changes from 1 commit
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
b09bc3d
Error object: add `type` link
ethanresnick Dec 26, 2015
ad623ef
Content Negotiation: update rules to account for `profile` parameter
ethanresnick Dec 26, 2015
3de79bf
Content negotiation: explain what a media type parameter is
ethanresnick Dec 26, 2015
dcf70a5
Query parameters: clean up
ethanresnick Dec 26, 2015
b09d759
Add the concept of "mappings"
ethanresnick Dec 26, 2015
c023bb1
Remove `code` member from error objects
ethanresnick Dec 26, 2015
348aa8d
Add anchor to the definition of a single link
ethanresnick Dec 27, 2015
715060e
Cleanup `code` formatting
ethanresnick Dec 28, 2015
c2ae234
Error object: clarify pointer member
ethanresnick Dec 28, 2015
ae1ac9b
Error objects: specify `missing` member
ethanresnick Dec 29, 2015
9b8235d
Add profile extension rules!
ethanresnick Dec 29, 2015
6cf30a9
Deprecate the old extension system
ethanresnick Dec 29, 2015
624b138
Extension registration: add new procedures
ethanresnick Dec 29, 2015
4ca869c
Merge remote-tracking branch 'origin' into profile-extensions
ethanresnick Apr 13, 2016
60d1652
Merge remote-tracking branch 'origin' into profile-extensions
ethanresnick Apr 13, 2016
2ff62f6
Merge remote-tracking branch 'origin/gh-pages' into profile-extensions
ethanresnick Apr 27, 2016
a22cc0e
"mappings" => "aliases" and remove naming restriction
ethanresnick Apr 27, 2016
baf3376
Error object: clarify that the code member isn't strictly "removed"
ethanresnick Apr 27, 2016
226141b
Extensions: Make registration optional but encouraged
ethanresnick Apr 27, 2016
f787eac
meta start
ethanresnick Apr 27, 2016
8510772
Merge remote-tracking branch 'origin/profile-extensions' into profile…
ethanresnick Apr 27, 2016
190079f
Merge branch 'gh-pages' into profile-extensions
ethanresnick Jul 15, 2017
f4ff261
Fix merge error
ethanresnick Jul 15, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add profile extension rules!
Closes #915.
  • Loading branch information
ethanresnick committed Apr 13, 2016
commit 9b8235d246fb44b5b87025b8b0c85c1eab1f8b8c
260 changes: 250 additions & 10 deletions _format/1.1/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ version: 1.1
## <a href="#introduction" id="introduction" class="headerlink"></a> Introduction

JSON API is a specification for how a client should request that resources be
fetched or modified, and how a server should respond to those requests.
fetched or modified, and how a server should respond to those requests. JSON API
can also be easily [extended](#extending).

JSON API is designed to minimize both the number of requests and the amount of
data transmitted between clients and servers. This efficiency is achieved
Expand Down Expand Up @@ -101,9 +102,12 @@ If a document does not contain a top-level `data` key, the `included` member

The top-level [links object][links] **MAY** contain the following members:

* `self`: the [link] that generated the current response document.
* `related`: a [related resource link] when the primary data represents a
resource relationship.
* `self`: a [link][link] whose URL is the URL that was requested to
produce the current response document.
* `related`: a [related resource link], allowed when the primary data
represents a resource relationship.
* `profile`: an array of [links][link], each giving the URI of a
[profile extension][extensions] in use in the document.
* [pagination] links for the primary data.

The document's "primary data" is a representation of the resource or collection
Expand Down Expand Up @@ -508,28 +512,31 @@ For example:
### <a href="#document-links" id="document-links" class="headerlink"></a> Links

Where specified, a `links` member can be used to represent links. The value
of each `links` member **MUST** be an object (a "links object").
of this member **MUST** be an object (a "links object").

<a href="#document-links-link" id="document-links-link"></a>
Each member of a links object is a "link". A link **MUST** be represented as
either:
Within this object, a link **MUST** be represented as either:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The prior language equated each member with a single link. The removal of the phrase creates the same issue I'm trying to resolve for relationships in #946. Another similarity to #946 is that the names of the links are not mentioned at all.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that there's an analogy between the text here and #946.

I faced a couple problems writing this section:

  1. With the profile key now holding multiple links, we ca no longer say "each value is a link".
  2. Because we haven't yet defined the relationship between links and RFC 5988, I didn't want to introduces a term for the key (i.e. I didn't want to say whether it's the links name or a relation).

So, given the above constraints, the wording in the PR was what I came up with.

Let's get this PR merged, and then we can figure out how to clarify things in #958. I'll link this thread there for reference.


* a string containing the link's URL.
* an object ("link object") which can contain the following members:
* `href`: a string containing the link's URL.
* `meta`: a meta object containing non-standard meta-information about the
link.

The following `self` link is simply a URL:
Except for the `profile` key, each key present in a links object **MUST** have
a single link as its value. The `profile` key, if present, **MUST** hold an
array of links.

For example, the following `self` link is simply a URL:

```json
"links": {
"self": "http://example.com/posts",
}
```

The following `related` link includes a URL as well as meta-information
about a related resource collection:
By contrast, the following `related` link includes a URL as well as
meta-information about a related resource collection:

```json
"links": {
Expand All @@ -542,6 +549,14 @@ about a related resource collection:
}
```

Here, the `profile` key specifies an array of `profile` links:

```json
"links": {
"profile": [{ "href": "http://jsonapi.org/ext/example-ext" }]
}
```

> Note: Additional members may be specified for links objects and link
objects in the future. It is also possible that the allowed values of
additional members will be expanded (e.g. a `collection` link may support an
Expand Down Expand Up @@ -579,6 +594,9 @@ for the URI `http://jsonapi.org/`:
These requirements ensure that your implementation will remain compatible
with future base specification additions.

> Note: Mappings are currently only used as part of the [extension system][extensions].
However, their use will likely be expanded in the future.

### <a href="#document-jsonapi-object" id="document-jsonapi-object" class="headerlink"></a> JSON API Object

A JSON API document **MAY** include information about its implementation
Expand Down Expand Up @@ -1780,6 +1798,225 @@ parameter from this specification, it **MUST** return `400 Bad Request`.
> Note: This is to preserve the ability of JSON API to make additive additions
to standard query parameters without conflicting with existing implementations.

## <a href="#extending" id="extending" class="headerlink"></a> Extending JSON API

An API **MAY** support one or more "profile extensions" to supplement the
capabalities of this specification.

A profile extension is a small, separate specification that defines a set of
values that can be added to a JSON API document, and the meaning of those values
at the different places they can occur.

Each profile extension **MUST** be registered with the JSON API
[extension registry](http://jsonapi.org/extensions/), so that others can find
and reuse the extension.

Upon completing registration, each extension is assigned a [URI](https://www.ietf.org/rfc/rfc3986.txt).

For requesting extensions and indicating those in use, the JSON API media type
defines a `profile` parameter. If present, the value of this parameter, **MUST**
be a space-separated (U+0020 SPACE, " ") list of profile extension URIs. This
list **MUST** be surrounded by quotation marks (U+0022 QUOTATION MARK, """), in
accordance with the HTTP specification.

### <a href="#extending-profile-extensions-processing" id="extending-profile-extensions-processing" class="headerlink"></a> Processing Extensions

The recipient of a document **MUST** ignore any profile extensions in that
document that it does not understand.

### <a href="#extending-profile-extensions-applying" id="extending-profile-extensions-applying" class="headerlink"></a> Adding Extensions to a Document

The client or the server **MAY** add profile extensions to a JSON API document,
whether or not the other party [requests](#extending-profile-extensions-requesting)
them. When one or more profile extensions are used in a JSON API document:

1. The document **MUST** have a [top-level][top level] [`links` object][links]
with a `profile` key, and that `profile` key **MUST** include a [link] to the
URI of each extension in use.

2. The document **MUST** define an [alias][mappings] for each extension's URI.

The alias for an extension's URI **MAY** be used as a key (an "extension-associated
key"). The value at any such key is interpreted according the specification of
the extension to which the key name maps.

The same extension-associated key **MAY** appear more than once in a given
document.

An extension-associated key **MUST NOT** be added at any location where the
extension's specification does not define how to interpret the key's value.

> In practice, extension-associated keys are only allowed in a subset of the
places where a meta object can occur. This is because extensions are also
[limited](#extending-profile-extensions-characteristics) in where they can
permit their data to appear. In particular, extension-associated keys are
_not_ allowed anywhere within attributes objects or meta objects, or as keys
directly under `relationships` and `links` objects.

The following document demonstrates these rules by adding a hypothetical
extension that has the URI `http://jsonapi.org/extensions/last-modified`:

```json
{
"mappings": {
"last-modified": "http://jsonapi.org/extensions/last-modified"
},
"links": {
"profile": ["http://jsonapi.org/extensions/last-modified"]
},
"data": {
"type": "people",
"id": "9",
"attributes": {
"first-name": "Dan",
"last-name": "Gebhardt"
},
"relationships": {
"father": {
"data": { "type": "people", "id": "7" },
"last-modified": "2013-09-24T00:00:00Z"
}
},
"last-modified": { "date": "2015-01-01T00:00:00Z", "fields": ["first-name"] }
}
}
```

The document above provides a [link] to the extension's URI in the `profile` key,
and gives that URI the alias `"last-modified"` (though any legal [alias][mappings]
name would do). Then, `"last-modified"` is used as an extension-associated
key throughout the document. The `"last-modified"` key holds values that have
different formats and meanings in each location that it appears, which is
allowed assuming the extension's specification describes those formats.

### <a href="#extending-profile-extensions-sending" id="extending-profile-extensions-sending" class="headerlink"></a> Sending Extended Documents

When sending a JSON API document that uses profile extensions, whether from the
server to the client or vice-versa, the `profile` parameter **MUST** be used in
the `Content-Type` header to indicate which extensions are in use.

For instance, the following header would be sent with a document that makes use
of the `http://jsonapi.org/ext/example-1/` and `http://jsonapi.org/ext/example-2/`
extensions:

```http
Content-Type: application/vnd.api+json; profile="http://jsonapi.org/ext/example-1/ http://jsonapi.org/ext/example-2/"
```

##### Handling `415 Unsupported Media Type`

When an older JSON API server that doesn't support the `profile` parameter
receives a document with profile extensions, it will respond with a
`415 Unsupported Media Type` error.

After attempting to rule out other possible causes of this error, a client that
receives a `415 Unsupported Media Type` **SHOULD** remove the profile extensions
it has applied to the document and retry its request without the `profile` media
type parameter. If this resolves the error, the client **SHOULD NOT** attempt to
use profile extensions in subsequent interactions with the same API.

> The most likely other causes of a 415 error are that the server doesn't
support JSON API at all or that the client has failed to provide a
[required extension](#extending-profile-extensions-required).


### <a href="#extending-profile-extensions-negotiation" id="extending-profile-extensions-negotiation" class="headerlink"></a> Negotiating Extensions

#### <a href="#extending-profile-extensions-requesting" id="extending-profile-extensions-requesting" class="headerlink"></a> Requesting Extensions

The client **MAY** request that certain profile extensions be applied to the
server's response by listing those extensions in a `profile` parameter in one
of its references to the JSON API media type in the `Accept` header.

For example, in the following request the client, the client asks that the
server apply the `http://jsonapi.org/extensions/last-modified` extension if
it is able to.

```http
Accept: application/vnd.api+json;profile="http://jsonapi.org/extensions/last-modified", application/vnd.api+json
```

> Note: The second instance of the JSON API media type in the example above is
required under the [client's content negotiation responsibilities](#content-negotiation-clients).
It is used to support old servers that don't understand the profile parameter.

The server **SHOULD** include as many of the requested extensions as it supports.

#### <a href="#extending-profile-extensions-required" id="extending-profile-extensions-required" class="headerlink"></a> Required Extensions

A server **SHOULD NOT** require that clients send documents containing certain
extensions, as such requirements reduce interoperability.

However, in the event that the server does require one or more extensions (e.g.
for authentication), and the client fails to use those extensions, the server
**MUST** send a `415 Unsupported Media Type` error. In the error's response body,
there **MUST** be an [error object][error objects] for each required extension
that is missing, and this error object **MUST**:

- have a [`type` link](#error-objects-links-type) who's URI is
`http://jsonapi.org/errors/missing-profile-extension`

- include the URI of the missing extension in the `extension` member of the
[`missing` object](#error-objects-source-missing).

### <a href="#extending-profile-extensions-characteristics" id="extending-profile-extensions-characteristics" class="headerlink"></a> Profile Extension Characteristics

Profile extensions are limited in how they can interact with this specification
and one another. These limitations have been chosen carefully to ensure that
multiple profile extensions can be used together safely; that changes to this
specification will not conflict with a profile extension's semantics; and that
profile extensions don't interfere with the interoperability of JSON API
implementations. Accordingly:

Profile extension designers **MUST NOT** assume that their extension will be
understood by the recipient of its data, or that it will be processed in any
particular order relative to the other extensions in use.

A profile extension **MUST** only define a set of allowed values, and the
meaning of those values. These values **MAY** be defined for use in any
spec-defined object that allows a [meta object][meta], at the same level where
that meta object is allowed to appear. The one exception is that an extension
**MUST NOT** define values for use in the [`jsonapi` object](#document-jsonapi-object).

> Note: the above restriction implies that profile extensions may not define
values for use within the specification-defined `"attributes"`, `"meta"`, or
`"mappings"` objects, or as a key in a [`links` object][links], because meta
objects are not allowed in these places.

The meaning of an extension-defined value **MAY** vary based on where it occurs
in the document but **MUST NOT** vary based on the presence or absence of other
profile extensions.

A profile extension **MAY** declare that data from other extensions can be added
to an object it defines. (Such data from a foreign extension would be added at a
key associated with that extension.) If an extension does this, it **MAY**
require that the extension whose data is being embedded meet certain functional
requirements. However, it **MUST NOT** require that the extension being embedded
be on a list of explicitly allowed extensions that it maintains.

Conversely, a profile extension **MAY** define a set of values that can be used
in objects added to the document by other profile extensions.

The keys in any profile-extension-defined objects **MUST** only contain the
characters a-z (U+0061 to U+007A).

> Note: Future keys defined by this specification will also follow the above
restriction, gauranteeing that extension alias names are differentiable from
keys with a fixed meaning.

Profile extensions **MAY** be updated over time to add new capabilities, by
revising their registration. However, any such changes **MUST** be [backwards and
forwards compatible](http://www.w3.org/2001/tag/doc/versioning-compatibility-strategies#terminology).

Profile extensions **MUST NOT** define new query parameters, fixed endpoints,
or HTTP headers or header values. They **MUST NOT** alter the JSON structure of
any concept defined in this specification, including to allow a superset of
JSON structures.

Additionally, profile extensions **MUST NOT** alter the meaning or processing
rules associated with any concept defined in this specification, including to
add additional meanings or constraints.

## <a href="#errors" id="errors" class="headerlink"></a> Errors

### <a href="#errors-processing" id="errors-processing" class="headerlink"></a> Processing Errors
Expand Down Expand Up @@ -1854,6 +2091,7 @@ An error object **MAY** have the following members:
to continue to support `code` if they must interact with older APIs. However,
new APIs must not produce error objects with this member.

[top level]: #document-top-level
[resource objects]: #document-resource-objects
[attributes]: #document-resource-object-attributes
[relationships]: #document-resource-object-relationships
Expand All @@ -1867,7 +2105,9 @@ An error object **MAY** have the following members:
[link]: #document-links-link
[links]: #document-links
[mappings]: #document-mappings
[extensions]: #extending
[error details]: #errors
[error objects]: #errror-objects
[member names]: #document-member-names
[pagination]: #fetching-pagination
[query parameters]: #query-parameters
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy