Beta
How the generated TypeScript client serializes query and path parameters per OpenAPI style, maps date/date-time to Date, and puts RFC 3339 on the wire.
Every generated parameter class serializes its path and query parameters
according to the style (and explode) your OpenAPI document declares —
simple and label and matrix for path parameters, form and
spaceDelimited and pipeDelimited and deepObject for query parameters.
This page covers the parts of that behavior that are easy to get wrong from
the outside: how a format: date/date-time property is typed and rendered,
what actually goes on the wire for each shape, and what a renamed property's
wire key is.
A schema property with format: date or format: date-time generates as a
TypeScript Date, not a string. This applies everywhere the property
appears — a scalar parameter, an array item, and a declared property of a
deepObject or resolvable form-style object parameter's nested object:
new ListItemsParameters({
fromTime: new Date('2026-08-13T10:20:30.000Z'), // format: date-time
onDate: new Date('2026-08-13T00:00:00.000Z'), // format: date
})
format: time is deliberately excluded from this mapping: a time-only string
(10:20:30) is not a valid Date constructor argument, so it stays a plain
string.
A nullable (or JSON Schema type: ['string', 'null']) format: date/date-time property still generates as Date, typed Date | null,
for every shape above — a scalar parameter, an array (nullable or not), and a
declared property nested in a deepObject or form-style object parameter:
new ListItemsParameters({
expiresAt: new Date('2026-08-13T10:20:30.000Z'), // format: date-time, nullable
notifyDates: null, // format: date, array, nullable
})
Serializing converts only a real Date instance to RFC 3339; a null value
follows the same omit-from-the-query-string rule as undefined. Deserializing
parses the wire value the same way as the non-nullable case below, assigning
a real Date on success and leaving the property untouched otherwise.
Every Date value is rendered as RFC 3339 before it is URL-encoded, never as
Date's own toString() output (Wed Aug 13 2026 ..., which no server
parsing RFC 3339 accepts):
format: date-time → the full timestamp, value.toISOString()
(2026-08-13T10:20:30.000Z).format: date → the date-only portion,
value.toISOString().split('T')[0] (2026-08-13).This applies uniformly to a scalar parameter, each item of an array-typed
parameter (range_dates=2026-01-01,2026-01-31 for a non-exploded array of
format: date), and each declared or dynamic entry of a deepObject or
resolvable form-style object parameter (below). Deserializing reverses it
with new Date(decoded), guarded by isNaN(dateValue.getTime()): a value
that fails to parse leaves the property untouched rather than assigning an
Invalid Date.
A type: object query parameter with style: deepObject generates a nested
model class with its own accessors, and serializes one query entry per
declared property — reading through the accessor, not by enumerating the
instance:
const url = new ListReportsParameters({
filter: new Filter({
since: new Date('2026-08-13T00:00:00.000Z'),
until: new Date('2026-08-13T10:20:30.000Z'),
}),
}).serializeUrl('/reports')
// filter[since]=2026-08-13, filter[until]=2026-08-13T10:20:30.000Z, once
// the query string is percent-decoded (each value is encodeURIComponent-ed
// before URLSearchParams itself percent-encodes the whole query string).
An undefined or null declared property is omitted from the query string
entirely, rather than serializing as an empty or literal "undefined" entry.
When the parameter's schema allows additional properties
(additionalProperties: { type: string, format: date }), the model carries a
dynamic-entry member typed Map<string, Date> (or Map<string, string> for
a non-date additionalProperties schema), and every entry in that map
serializes with the additionalProperties schema's own format:
new Filter({ additionalProperties: new Map([['region', 'eu']]) })
Deserializing mirrors the same split: a bracketed key that matches a declared
property name converts through that property's own format (Date, when it is
one); every other bracketed key goes into the additionalProperties map.
Nested objects or arrays inside a deepObject value are not supported —
OpenAPI itself defines no wire format for them, so a property typed that way
keeps the previous, best-effort String(val) rendering rather than gaining
one.
A type: object query parameter with style: form (the default style for
query parameters) serializes the same way once its schema resolves to a
single object model — reading through each declared property's accessor,
never by enumerating the instance. explode changes only the wire shape, not
which properties are read:
new ListItemsParameters({
filter: new Filter({
since: new Date('2026-08-13T00:00:00.000Z'),
until: new Date('2026-08-13T10:20:30.000Z'),
}),
}).serializeUrl('/items')
explode: true (the query default) puts each declared, present property on
its own top-level query parameter, keyed by the original schema property
name: since=2026-08-13&until=2026-08-13T10%3A20%3A30.000Z.explode: false joins present declared properties, plus dynamic entries,
into the single comma-separated value the form style defines for an
object: filter=since,2026-08-13,until,2026-08-13T10%3A20%3A30.000Z. A
value containing a literal comma is encodeURIComponent-escaped before
joining, so it survives the round trip; deserializing splits the raw value
on its structural commas before decoding each piece, the reverse order of
a decode-then-split approach, which would also split apart an escaped comma
that was part of an entry's own value.An undefined or null declared property is omitted, in both explode modes,
rather than serializing as an empty or literal "undefined" entry.
When the parameter's schema allows additional properties, dynamic entries
serialize the same way deepObject's do — from the model's
additionalProperties map, with that schema's own date format — in both
explode modes. Deserializing them back is asymmetric between the two:
explode: false puts unmatched keys from the comma list into the
additionalProperties map, the same as deepObject; explode: true does
not read dynamic keys back at all, only the declared ones, because an
unmatched top-level query parameter next to a form's other parameters is
ambiguous.
Nested objects or arrays inside a form-style object value are not
supported, for the same reason as deepObject. A schema with no single
resolvable object model (a oneOf/union, for instance) keeps the generic
Object.entries emission instead, unchanged.
A generated property name is the constrained (and, when a raw JSON Schema key would collide or is not a valid identifier, renamed — see Model naming) TypeScript identifier, but the wire key — what actually appears in the query string or path — is always the original schema property name:
// schema property "on_Date" renders as the accessor `onDate`
new Filter({ onDate: new Date('2026-08-13T00:00:00.000Z') })
// -> filter[on_Date]=2026-08-13, not filter[onDate]=...
This applies to every style, not only deepObject: a path or query parameter
whose own name Modelina had to rename still serializes and deserializes
against its original schema name on the wire.
A header with format: date or format: date-time (nullable or not) is typed
Date, and follows the same RFC 3339 rule as a query or path parameter:
serializeGetItemHeadersHeaders({ requestedAt: new Date('2026-08-13T10:20:30.000Z') })
// -> { 'X-Requested-At': '2026-08-13T10:20:30.000Z' }
deserializeGetItemHeadersHeaders({ 'x-requested-at': '2026-08-13T10:20:30.000Z' })
// -> { requestedAt: Date }
A null header value falls back to String(...) on serialization, the same
as any other nullable header kind. Deserializing an invalid or missing date
string leaves the property untouched — the same rule every date parameter
above follows — rather than assigning an Invalid Date. Every other header
kind (number, boolean, array, plain string) is unaffected.