In OpenAPI, how do the style and explode keywords change how an array query parameter appears in the URL?
answer
- The schema alone leaves the URL ambiguous
- Two keywords, one picks the separator
- The other decides repeated keys
- Its default depends on the style chosen
- Query and path start from different defaults
basics
~20 sOpenAPI's style picks the serialization rule and explode says whether each array item gets its own key. Query parameters default to style: form with explode: true, giving tags=a&tags=b; explode: false gives tags=a,b. spaceDelimited and pipeDelimited use spaces or pipes instead.
solid answer
~40 sA `schema` alone does not say how a non-scalar value is written into a URL, so OpenAPI adds `style` and `explode`. For query parameters the default is `style: form` with `explode: true`, which repeats the key: `?tags=blue&tags=black`. Set `explode: false` and the same array becomes `?tags=blue,black`. `spaceDelimited` and `pipeDelimited` (with `explode: false`) give `?tags=blue%20black` and `?tags=blue|black`. Path and header parameters default to `style: simple`, which is comma-separated: `/tags/blue,black`. Path also offers `matrix` (`;tags=blue,black`) and `label` (`.blue.black`). The defaults matter because `explode` defaults to `true` only when the style is `form`, and `false` otherwise. Getting this wrong is silent — the document and the code both look fine, and the generated client builds a URL the server does not parse.
code
yaml · 28 linesparameters:
- name: color
in: query
description: Repeated key form - color=blue&color=black
schema:
type: array
items:
type: string
style: form
explode: true
- name: shade
in: query
description: Comma-joined form - shade=light,dark
schema:
type: array
items:
type: string
style: form
explode: false
- name: sizes
in: query
description: Pipe-joined form - sizes=s|m|l
schema:
type: array
items:
type: string
style: pipeDelimited
explode: falsego deeper
Know that an array query parameter can be written as repeated keys or as one comma-joined value, and that OpenAPI has keywords that choose between them.
Be ready to state the defaults per location, produce the wire form for form with each explode value, and name which styles are query-only versus path-only.
Show that you check what the actual server framework parses before writing the document, and that you declare style and explode explicitly rather than trusting a default nobody remembers.
Own the convention across the estate — one serialization style for list parameters, enforced in review — so generated clients from different teams do not disagree about the same query string.
## The problem these keywords solve A JSON Schema tells you a query parameter is an array of strings. It does not tell you whether the wire form is `?tags=a&tags=b`, `?tags=a,b`, `?tags=a%20b`, or `?tags[]=a&tags[]=b`. HTTP has no single answer, and servers differ. OpenAPI 3.x therefore adds two keywords on the Parameter Object — `style` and `explode` — modelled on URI Template expansion (RFC 6570). Together they make the wire form unambiguous, which is what lets a generated client and a generated server agree. ## The style values and where each is allowed - **`form`** — query and cookie parameters. The default there. - **`simple`** — path and header parameters. The default there. Comma-separated. - **`spaceDelimited`** — query only. Values joined by a space (percent-encoded as `%20`). - **`pipeDelimited`** — query only. Values joined by `|`. - **`deepObject`** — query only, and only for objects: `color[R]=100`. - **`matrix`** — path only. Semicolon-prefixed, `;color=blue`. - **`label`** — path only. Dot-prefixed, `.blue`. ## The defaults, which are the whole trap `style` defaults to `form` for `query` and `cookie`, and to `simple` for `path` and `header`. `explode` defaults to `true` when `style` is `form`, and to `false` for every other style. So writing nothing at all on a query array means `form` + `explode: true` — repeated keys. ## Array serialization, side by side Take a query parameter named `color` whose value is the array `["blue", "black", "brown"]`: - `form`, `explode: true` (the default): `color=blue&color=black&color=brown` - `form`, `explode: false`: `color=blue,black,brown` - `spaceDelimited`, `explode: false`: `color=blue%20black%20brown` - `pipeDelimited`, `explode: false`: `color=blue|black|brown` For the same array in a path parameter: - `simple` (default, either explode value): `blue,black,brown` - `matrix`, `explode: false`: `;color=blue,black,brown` - `matrix`, `explode: true`: `;color=blue;color=black;color=brown` - `label`, `explode: false`: `.blue.black.brown` ## Primitives and objects For a **primitive**, `explode` changes nothing in most styles — `form` on a primitive is just `color=blue` either way — so the keywords only start to matter once the schema is an array or an object. For an **object** `{"R": 100, "G": 200, "B": 150}` in a query parameter: `form` with `explode: false` yields `color=R,100,G,200,B,150`; `form` with `explode: true` flattens the object into top-level keys, `R=100&G=200&B=150`, which loses the parameter name entirely; `deepObject` with `explode: true` yields `color[R]=100&color[G]=200&color[B]=150`. ## allowReserved A third query-only keyword, `allowReserved`, defaults to `false` and says whether the reserved characters `:/?#[]@!$&'()*+,;=` may appear unencoded in the value. Turning it on is occasionally needed for values that are themselves URLs or paths, and it is a common source of disagreement between a generated client that percent-encodes and a server that does not decode twice. ## Version notes `style` and `explode` are OpenAPI 3.x keywords. Swagger 2.0 expressed the same idea with a single `collectionFormat` field taking `csv`, `ssv`, `tsv`, `pipes` or `multi`; `multi` is the ancestor of `form` + `explode: true`, and `csv` of `form` + `explode: false`. When migrating a 2.0 document, every `collectionFormat` has to be translated, and a silent default of `csv` in 2.0 becomes a silent default of exploded form in 3.x — the opposite wire format. ## Why interviewers ask Because the failure is invisible on paper. Both sides validate, both sides generate, and then the server sees one query parameter with the literal value `blue,black,brown` while the framework expected repeated keys — or the reverse. The fix is always to state `style` and `explode` explicitly on any array or object parameter rather than relying on a default that half the team misremembers, and to confirm what the actual server framework parses before writing the document.
- What are the default style and explode values for a query parameter if you write neither?`style` defaults to `form` and, because the style is `form`, `explode` defaults to `true`. So an array query parameter with no serialization keywords is sent as repeated keys: `?tags=a&tags=b`. For every other style `explode` defaults to `false`, which is why a `pipeDelimited` parameter joins values without you saying anything.
- What does allowReserved do on an OpenAPI query parameter?`allowReserved` is query-only and defaults to `false`, meaning reserved characters such as `:/?#[]@!$&'()*+,;=` are percent-encoded. Setting it to `true` declares that the value may carry those characters unencoded — useful when the value is itself a URL or path. It changes what a generated client emits, so both sides must agree on the decoding.
- How does the path-only matrix style serialize an array?`matrix` is semicolon-prefixed. With `explode: false` the array `[blue, black]` for a parameter named `color` becomes `;color=blue,black`; with `explode: true` it becomes `;color=blue;color=black`. It comes from URI Template path-style expansion and is rare in practice — most APIs use plain path segments and put lists in the query string instead.
saying these in an interview costs you the question
- Thinks explode always defaults to true
- Believes the schema alone determines the URL format
- Says style applies to the request body too
- Uses deepObject for an array
- Assumes 2.0 collectionFormat csv maps to the 3.x default