Make a field optional
Suffix a key with `?` so a field that never receives a value is dropped instead of erroring.
Rendered from
docs/how-to/make-a-field-optional.md
in the engine repository, where a correction belongs, and where the
test suite executes every example on this page.
Some fields are genuinely sometimes-absent, and a schema that demands
them anyway teaches producers to send empty strings. Suffix the key
with ? instead. An optional field that never receives a concrete
value is dropped from the output:
record: { id: integer, note?: string }
record: { id: 1 }
{
"record": {
"id": 1
}
}
Dropped means absent: no note, not note: null. Supplying a value
keeps the field, checked against its constraint as usual:
record: { id: integer, note?: string }
record: { id: 1, note: hi }
{
"record": {
"id": 1,
"note": "hi"
}
}
An optional key with a ranked default is filled rather than dropped, because the default is a concrete value arriving:
record: { id: integer, retries?: *3 | integer }
record: { id: 1 }
{
"record": {
"id": 1,
"retries": 3
}
}
Use note?: for “may not exist” and retries?: *3 | integer for
“always exists, sender may omit”. The two read almost the same and
generate differently.
An optional key is still a declared key, so it coexists with
close: the sealed map admits the key
when it arrives and drops it when it does not:
config: close({ id:integer note?:string })
config: id: 1
{
"config": {
"id": 1
}
}
The full rules, including how optionality survives references, are in
Optional keys ?. For
defaults on their own, see provide defaults;
on a JSON Schema export an optional key is simply absent from
required: see export JSON Schema.