Skip to content

Commit a47164a

Browse files
authored
feat(query-params): clarify parsing/serializing, individual params vs family (json-api#1308)
* feat(query-params): clarify parsing/serializing, individual params vs family Addresses json-api#1302, json-api#1304.
1 parent 82b6aad commit a47164a

File tree

3 files changed

+119
-43
lines changed

3 files changed

+119
-43
lines changed

_format/1.1/index.md

Lines changed: 110 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -644,7 +644,7 @@ first or last character:
644644

645645
The following characters **MUST NOT** be used in member names:
646646

647-
- U+002B PLUS SIGN, "+" _(used for ordering)_
647+
- U+002B PLUS SIGN, "+" _(has overloaded meaning in URL query strings)_
648648
- U+002C COMMA, "," _(used as a separator between relationship paths)_
649649
- U+002E PERIOD, "." _(used as a separator within relationship paths)_
650650
- U+005B LEFT SQUARE BRACKET, "[" _(used in sparse fieldsets)_
@@ -982,7 +982,7 @@ responses, in accordance with
982982

983983
An endpoint **MAY** return resources related to the primary data by default.
984984

985-
An endpoint **MAY** also support an `include` request parameter to allow the
985+
An endpoint **MAY** also support an `include` query parameter to allow the
986986
client to customize which related resources should be returned.
987987

988988
If an endpoint does not support the `include` parameter, it **MUST** respond
@@ -1060,9 +1060,9 @@ resource or relationship.
10601060
### <a href="#fetching-sparse-fieldsets" id="fetching-sparse-fieldsets" class="headerlink"></a> Sparse Fieldsets
10611061

10621062
A client **MAY** request that an endpoint return only specific [fields] in the
1063-
response on a per-type basis by including a `fields[TYPE]` parameter.
1063+
response on a per-type basis by including a `fields[TYPE]` query parameter.
10641064

1065-
The value of the `fields` parameter **MUST** be a comma-separated (U+002C
1065+
The value of any `fields[TYPE]` parameter **MUST** be a comma-separated (U+002C
10661066
COMMA, ",") list that refers to the name(s) of the fields to be returned.
10671067

10681068
If a client requests a restricted set of [fields] for a given resource type,
@@ -1075,8 +1075,8 @@ Accept: application/vnd.api+json
10751075
```
10761076

10771077
> Note: The above example URI shows unencoded `[` and `]` characters simply for
1078-
readability. In practice, these characters must be percent-encoded, per the
1079-
requirements [in RFC 3986](http://tools.ietf.org/html/rfc3986#section-3.4).
1078+
readability. In practice, these characters should be percent-encoded. See
1079+
"[Square Brackets in Parameter Names](#appendix-query-details-square-brackets)".
10801080

10811081
> Note: This section applies to any endpoint that responds with resources as
10821082
primary or included data, regardless of the request type. For instance, a
@@ -1089,7 +1089,7 @@ A server **MAY** choose to support requests to sort resource collections
10891089
according to one or more criteria ("sort fields").
10901090

10911091
> Note: Although recommended, sort fields do not necessarily need to
1092-
correspond to resource attribute and association names.
1092+
correspond to resource attribute and relationship names.
10931093

10941094
> Note: It is recommended that dot-separated (U+002E FULL-STOP, ".") sort
10951095
fields be used to request sorting based upon relationship attributes. For
@@ -1165,32 +1165,24 @@ particular link is unavailable.
11651165
Concepts of order, as expressed in the naming of pagination links, **MUST**
11661166
remain consistent with JSON:API's [sorting rules](#fetching-sorting).
11671167

1168-
The `page` query parameter is reserved for pagination. Servers and clients
1169-
**SHOULD** use this key for pagination operations.
1168+
The `page` [query parameter family] is reserved for pagination. Servers and
1169+
clients **SHOULD** use these parameters for pagination operations.
11701170

1171-
> Note: JSON:API is agnostic about the pagination strategy used by a server.
1172-
Effective pagination strategies include (but are not limited to):
1173-
page-based, offset-based, and cursor-based. The `page` query parameter can
1174-
be used as a basis for any of these strategies. For example, a page-based
1175-
strategy might use query parameters such as `page[number]` and `page[size]`,
1176-
an offset-based strategy might use `page[offset]` and `page[limit]`, while a
1177-
cursor-based strategy might use `page[cursor]`.
1178-
1179-
> Note: The example query parameters above use unencoded `[` and `]` characters
1180-
simply for readability. In practice, these characters must be percent-encoded,
1181-
per the requirements in [RFC 3986](http://tools.ietf.org/html/rfc3986#section-3.4).
1171+
> Note: JSON API is agnostic about the pagination strategy used by a server, but
1172+
> the `page` query parameter family can be used regardless of the strategy
1173+
> employed. For example, a page-based strategy might use query parameters such
1174+
> as `page[number]` and `page[size]`, while a cursor-based strategy might use
1175+
> `page[cursor]`.
11821176
11831177
> Note: This section applies to any endpoint that responds with a resource
11841178
collection as primary data, regardless of the request type.
11851179

11861180
### <a href="#fetching-filtering" id="fetching-filtering" class="headerlink"></a> Filtering
11871181

1188-
The `filter` query parameter is reserved for filtering data. Servers and clients
1189-
**SHOULD** use this key for filtering operations.
1182+
The `filter` [query parameter family] is reserved for filtering data. Servers
1183+
and clients **SHOULD** use these parameters for filtering operations.
11901184

1191-
> Note: JSON:API is agnostic about the strategies supported by a server. The
1192-
`filter` query parameter can be used as the basis for any number of filtering
1193-
strategies.
1185+
> Note: JSON API is agnostic about the strategies supported by a server.
11941186
11951187
## <a href="#crud" id="crud" class="headerlink"></a> Creating, Updating and Deleting Resources
11961188

@@ -1809,9 +1801,43 @@ responses, in accordance with
18091801

18101802
## <a href="#query-parameters" id="query-parameters" class="headerlink"></a> Query Parameters
18111803

1812-
Implementation-specific query parameter names **MUST** adhere to the same
1813-
constraints as [member names], with the additional requirement that they
1814-
**MUST** contain at least one non a-z character (i.e., outside U+0061 to U+007A).
1804+
### <a href="#query-parameters-families" id="query-parameters-families" class="headerlink"></a> Query Parameter Families
1805+
Although "query parameter" is a common term in everyday web development, it is
1806+
not a well-standardized concept. Therefore, JSON:API provides its own
1807+
[definition of a query parameter](#appendix-query-details).
1808+
1809+
For the most part, JSON:API's definition coincides with colloquial usage, and its
1810+
details can be safely ignored. However, one important consequence of this
1811+
definition is that a URL like the following is considered to have two distinct
1812+
query parameters:
1813+
1814+
```
1815+
/?page[offset]=0&page[limit]=10
1816+
```
1817+
1818+
The two parameters are named `page[offset]` and `page[limit]`; there is no
1819+
single `page` parameter.
1820+
1821+
In practice, however, parameters like `page[offset]` and `page[limit]` are
1822+
usually defined and processed together, and it's convenient to refer to them
1823+
collectively. Therefore, JSON:API introduces the concept of a query parameter
1824+
family.
1825+
1826+
A "query parameter family" is the set of all query parameters whose name starts
1827+
with a "base name", followed by zero or more instances of empty square brackets
1828+
(i.e. `[]`) or square-bracketed legal member names. The family is referred to
1829+
by its base name.
1830+
1831+
For example, the `filter` query parameter family includes parameters named:
1832+
`filter`, `filter[x]`, `filter[]`, `filter[x][]`, `filter[][]`, `filter[x][y]`,
1833+
etc. However, `filter[_]` is not a valid parameter name in the family, because
1834+
`_` is not a valid [member name][member names].
1835+
1836+
### <a href="#query-parameters-custom" id="query-parameters-custom" class="headerlink"></a> Implementation-Specific Query Parameters
1837+
Implementations **MAY** support custom query parameters. However, the names of
1838+
these query parameters **MUST** come from a [family][query parameter family]
1839+
whose base name is a legal [member name][member names] and also contains at least
1840+
one non a-z character (i.e., outside U+0061 to U+007A).
18151841

18161842
It is **RECOMMENDED** that a capital letter (e.g. camelCasing) be used to
18171843
satisfy the above requirement.
@@ -1962,6 +1988,10 @@ To do so, a server **MAY** define an internal mapping from query parameter names
19621988
to profile URIs. The profile URI for a query parameter name in this mapping
19631989
**MUST NOT** change over time.
19641990

1991+
> Note: the server may choose to map all query parameter names from the same
1992+
> [family][query parameter family] to one profile URI. Or, it may choose to map
1993+
> only specific query parameter names.
1994+
19651995
If a requested URL does not contain the `profile` query parameter and does
19661996
contain one or more query parameters in the server's internal mapping, the
19671997
server may act as though the request URL contained a `profile` query parameter
@@ -1970,23 +2000,23 @@ found in the server's internal mapping for the query parameters in use on the
19702000
request.
19712001

19722002
For example, the server might support a profile that defines a meaning for the
1973-
values of the `filter` query param. Then, it could define its internal
2003+
values of the `page[cursor]` query param. Then, it could define its internal
19742004
param name to profile uri mapping like so:
19752005

19762006
```json
1977-
{ "filter": "https://example.com/my-filter-profile" }
2007+
{ "page[cursor]": "https://example.com/pagination-profile" }
19782008
```
19792009

19802010
Accordingly, a request for:
19812011

19822012
```
1983-
https://example.com/?filter=xyz
2013+
https://example.com/?page[cursor]=xyz
19842014
```
19852015

19862016
would be interpreted by the server as:
19872017

19882018
```
1989-
https://example.com/?filter=xyz&profile=https://example.com/my-filter-profile
2019+
https://example.com/?page[cursor]=xyz&profile=https://example.com/pagination-profile
19902020
```
19912021

19922022

@@ -2191,8 +2221,8 @@ objects. A profile **MUST NOT** define/assign a meaning to document members
21912221
in areas of the document reserved for future use by the JSON:API specification.
21922222

21932223
For example, it would be illegal for a profile to define a new key in a
2194-
document's [top-level][top level] object, or in a [links object], as JSON:API
2195-
implementations are not allowed to add custom keys in those areas.
2224+
document's [top-level][top level] object, or in a [links object][links], as
2225+
JSON API implementations are not allowed to add custom keys in those areas.
21962226

21972227
Likewise, a profile **MAY** assign a meaning to query parameters or parameter
21982228
values whose details are left up to each implementation, such as `filter` and
@@ -2326,6 +2356,51 @@ An error object **MAY** have the following members:
23262356
* `meta`: a [meta object][meta] containing non-standard meta-information about the
23272357
error.
23282358

2359+
## <a href="#appendix" id="appendix" class="headerlink"></a> Appendix
2360+
### <a href="#appendix-query-details" id="appendix-query-details" class="headerlink"></a> Query Parameters Details
2361+
#### <a href="#appendix-query-details-parsing" id="appendix-query-details-parsing" class="headerlink"></a> Parsing/Serialization
2362+
A query parameter is a name–value pair extracted from, or serialized into, a
2363+
URI's query string.
2364+
2365+
To extract the query parameters from a URI, an implementation **MUST** run the
2366+
URI's query string, excluding the leading question mark, through the
2367+
[`application/x-www-form-urlencoded` parsing algorithm](https://url.spec.whatwg.org/#urlencoded-parsing),
2368+
with one exception: JSON:API allows the specification that defines a query
2369+
parameter's usage to provide its own rules for parsing the parameter's value
2370+
from the `value` bytes identified in steps 3.2 and and 3.3 of the `application/x-www-form-urlencoded`
2371+
parsing algorithm. The resulting value might not be a string.
2372+
2373+
> Note: In general, the query string parsing built in to servers and browsers
2374+
> will match the process specified above, so most implementations do not need
2375+
> to worry about this.
2376+
>
2377+
> The `application/x-www-form-urlencoded` format is referenced because it is
2378+
> the basis for the `a=b&c=d` style that almost all query strings use today.
2379+
>
2380+
> However, `application/x-www-form-urlencoded` parsing contains the bizarre
2381+
> historical artifact that `+` characters must be treated as spaces, and it
2382+
> requires that all values be percent-decoded during parsing, which makes it
2383+
> impossible to use [RFC 3986 delimiter characters](https://tools.ietf.org/html/rfc3986#section-2.2)
2384+
> as delimiters. These issues motivate the exception that JSON:API defines above.
2385+
2386+
Similarly, to serialize a query parameter into a URI, an implementation **MUST**
2387+
use the [the `application/x-www-form-urlencoded` serializer](https://url.spec.whatwg.org/#concept-urlencoded-serializer),
2388+
with the corresponding exception that a parameter's value — but not its name —
2389+
may be serialized differently than that algorithm requires, provided the
2390+
serialization does not interfere with the ability to parse back the resulting URI.
2391+
2392+
#### <a href="#appendix-query-details-square-brackets" id="appendix-query-details-square-brackets" class="headerlink"></a> Square Brackets in Parameter Names
2393+
With [query parameter families][query parameter family], JSON:API allows for
2394+
query parameters whose names contain square brackets (i.e., U+005B "[" and
2395+
U+005D "]").
2396+
2397+
According to the query parameter serialization rules above, a compliant
2398+
implementation will percent-encode these square brackets. However, some URI
2399+
producers — namely browsers — do not always encode them. Servers **SHOULD**
2400+
accept requests in which these square brackets are left unencoded in a query
2401+
parameter's name. If a server does accept these requests, it **MUST** treat the
2402+
request as equivalent to one in which the square brackets were percent-encoded.
2403+
23292404
[top level]: #document-top-level
23302405
[resource objects]: #document-resource-objects
23312406
[attributes]: #document-resource-object-attributes
@@ -2348,3 +2423,4 @@ An error object **MAY** have the following members:
23482423
[error objects]: #errror-objects
23492424
[member names]: #document-member-names
23502425
[pagination]: #fetching-pagination
2426+
[query parameter family]: #query-parameters-families

examples/index.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,15 +50,15 @@ Content-Type: application/vnd.api+json
5050
}
5151
```
5252

53-
Request with `fields` parameter:
53+
Request with `fields[articles]` and `fields[people]` parameters:
5454

5555
```http
5656
GET /articles?include=author&fields[articles]=title,body,author&fields[people]=name HTTP/1.1
5757
```
5858

5959
> Note: The above example URI shows unencoded `[` and `]` characters simply
60-
for readability. In practice, these characters must be percent-encoded, as
61-
noted in the base specification.
60+
for readability. In practice, these characters should be percent-encoded, as
61+
noted in the base specification. See "[Square Brackets in Parameter Names](/format/1.1/#appendix-query-details-square-brackets)".
6262

6363
Here we want `articles` objects to have fields `title`, `body` and `author` only and `people` objects to have `name` field only.
6464

@@ -124,8 +124,8 @@ Content-Type: application/vnd.api+json
124124
```
125125

126126
> Note: The above example URI shows unencoded `[` and `]` characters simply
127-
for readability. In practice, these characters must be percent-encoded, as
128-
noted in the base specification.
127+
for readability. In practice, these characters should be percent-encoded, as
128+
noted in the base specification. See "[Square Brackets in Parameter Names](/format/1.1/#appendix-query-details-square-brackets)".
129129

130130
## <a href="#pagination" id="pagination" class="headerlink"></a> Pagination Links
131131

@@ -168,8 +168,8 @@ Content-Type: application/vnd.api+json
168168
```
169169

170170
> Note: The above example URIs show unencoded `[` and `]` characters simply
171-
for readability. In practice, these characters must be percent-encoded, as
172-
noted in the base specification.
171+
for readability. In practice, these characters should be percent-encoded, as
172+
noted in the base specification. See "[Square Brackets in Parameter Names](/format/1.1/#appendix-query-details-square-brackets)".
173173

174174
> Note: Putting a property like `"totalPages"` in `"meta"` can be a convenient way
175175
to indicate to clients the total number of pages in a collection (as opposed to

recommendations/index.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,8 @@ for individual resource URLs should still apply when forming `self` links.
113113
## <a href="#filtering" id="filtering" class="headerlink"></a> Filtering
114114

115115
The base specification is agnostic about filtering strategies supported by a
116-
server. The `filter` query parameter is reserved to be used as the basis for
117-
any filtering strategy.
116+
server. The `filter` query parameter family is reserved to be used as the basis
117+
for any filtering strategy.
118118

119119
It's recommended that servers that wish to support filtering of a resource
120120
collection based upon associations do so by allowing query parameters that

0 commit comments

Comments
 (0)
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