Skip to content

Draw out distinct concepts of a query param and "parameter family" #1304

@ethanresnick

Description

@ethanresnick

Right now, the JSON:API spec uses the terms "query parameter" and "query parameter name" in a way that's inconsistent with other web standards, and internally inconsistent throughout the spec.

Consider the URL /articles?page[cursor]=xyz&page[size]=10. Does that URL have one query parameter (named page) or two (one named page[cursor] and one named page[size])?

From a standards POV, the best/only answer comes from the WHATWG Url standard, which says (see step 4) that it has two. Accordingly, the following code logs first "page[cursor]" and then"page[size]":

for(let [k,v] of new URLSearchParams("?page[cursor]=xyz&page[size]=10")) {
  console.log(k);
}

(Other standards, like RFC 3986 and the HTTP RFCs don't have a concept of distinct query parameters at all; they only have the idea of a single query string.)

When the JSON:API spec says, though, that: "The page query parameter is reserved for pagination", we're clearly intending to cover the whole set of page[offset], page[cursor], page[xxx][yy] parameters with that statement — not just the literal parameter page.

Therefore, I propose that we explicitly define the concept of a "query parameter family", distinct from an individual query parameter. That will let us use the term "query parameter" in a way that's consisten with WHATWG and, perhaps more importantly, it'll clear up a few spec ambiguities:

  1. In error objects, we can clarify that the "parameter" key is supposed to refer to the specific parameter, and not the parameter family's name. For example:

    The request GET /xxx?fields[books]=tilte&fields[people]=name has a typo: the title field has been misspelled as tilte. In the resulting error object, I think we want something like:

    { /* ... */  "source": { "parameter": "fields[books]" } }

    Having the parameter be fields[books] is more useful than having it just be fields but, at the moment, it's deeply ambiguous which is correct. In the sparse fieldsets section of the spec, for example, we manage to refer to both "a fields[TYPE] parameter" (which implies field[books] could be the source) and "the fields parameter" (which seems to imply the opposite).

  2. When we say that "Implementation specific query parameters MUST adhere to the same constraints as member names", I don't think we're intending to disallow customParam[xxx] as a parameter name — even though it contains square brackets, which are not valid in member names. We can make this clearer by saying that implementation-specific query parameter names must come from a family whose name adheres to the member name constraints. This is similar to the point above about us actually intending to reserve the entire page family for pagination, and not just the literal page parameter.

  3. Finally, when we specify how the server can infer the value of the profile query parameter, we say that "a server MAY define an internal mapping from query parameter names to profile URIs". In this usage, I think we actually want to give the server the choice about whether to map a whole family of parameter names to a given profile, or whether to just map concrete parameters. For example, a server might want to map the presence page[offset] query parameter to one profile, and a page[cursor] parameter to another, so that both pagination schemes can be supported (without need for the profile parameter). By contrast, for a filtering profile, the server might want to map all parameters in the filter family to that profile, to support (e.g.) arbitrary operators that might go in the concrete parameter name (?filter[myCustomOperator]). Having a distinction between a parameter and a parameter family would let us specify this as well.

So, with those motivating use cases, here are the definitions I'd propose:

  • A query parameter is a (name, value) pair that's part of a URL's query string. The name of a query parameter is serialized to and parsed from the URL per the process in WHATWG URL. (Under this second sentence, the URL ?fields[books]=x&fields[people]=y has two query parameters.)

  • A query parameter name family is a set of query parameter names derived from a base name. The base name must be a valid JSON:API member name. The family includes all query parameter names that start with the base name and are followed by zero or more instances of the square-bracket-surrounded legal member names. In ABNF:

    query-name-family-member = base-name *( "[" *legal-member-name "]" )
    

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      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