jq defaults without overwriting false: choose null or missing-key behavior
By ON Lab · Sources checked November 8, 2026
jq's // alternative operator uses the fallback for both null and false. If an existing false value must remain false, use an explicit null check or has("key"), depending on whether a present null should also be preserved. Decide that policy before choosing a default expression.
The reader question behind this guide asks for a get-or-default operation: return an object's existing property, but supply a default when the property does not exist. A false default can hide a policy mistake because replacing false with false looks correct. We used a true default in a local test so the difference is visible.
Three different default policies
These filters assume each input is an object and the property name is enabled. They do not define behavior for arbitrary arrays, scalars or nested schemas.
| Policy | Filter | Present false | Present null |
|---|---|---|---|
| Use the default for false and null | .enabled // true | Becomes true | Becomes true |
| Use the default for null or a missing property | if .enabled == null then true else .enabled end | Stays false | Becomes true |
| Use the default only when the key is missing | if has("enabled") then .enabled else true end | Stays false | Stays null |
All three policies can be useful. The mistake is treating them as interchangeable. For a configuration flag, a deliberate false may mean “disabled,” while a missing key means “use the default.” In another schema, null may mean “unknown” and need to remain visible instead of being converted into a default.
Test the distinction with a small input
Save this example as a new file named cases.json. It contains no personal or live configuration data:
[
{},
{"enabled": null},
{"enabled": false},
{"enabled": true},
{"enabled": 0},
{"enabled": ""}
]
Run each filter separately in a POSIX-style shell:
jq -c '.[] | .enabled // true' cases.json
jq -c '.[] | if .enabled == null then true else .enabled end' cases.json
jq -c '.[] | if has("enabled") then .enabled else true end' cases.json
We ran these filters locally with the installed jq binary and compared parsed results, not just terminal colors or exit messages. For the six objects in order, we obtained:
| Input property | Alternative operator | Null check | Key-presence check |
|---|---|---|---|
| Missing | true | true | true |
| null | true | true | null |
| false | true | false | false |
| true | true | true | true |
| 0 | 0 | 0 | 0 |
| Empty string | Empty string | Empty string | Empty string |
The zero and empty-string rows matter if you come from a language where these are treated like false in a fallback expression. Our test confirms that the shown jq alternative expression preserved both. Do not add conversions unless your schema actually requires them.
Apply the policy at the right object
For an object nested under columns.name, move to that object before testing its key:
jq '.columns.name | if has("required") then .required else false end' input.json
Here has("required") asks about the current column object. Calling it at the document root would inspect a different object. Replace the path and property with those from your actual schema, and test a missing property, present false and present null before adopting the expression.
If your intended default is false and both false and null are allowed to collapse to false, the shorter .required // false can be appropriate. Its shortness does not make it wrong; the question is whether its treatment of null matches your intended contract.
Do not confuse defaults with validation
These expressions preserve existing numbers and strings too. That is deliberate for a generic get-or-default operation, but it does not prove a field is a Boolean. If the downstream system requires only true or false, validate the type separately rather than assuming a fallback expression enforces it.
This guide also does not cover filters that generate several results, filtering an object out entirely, or aggregation over an empty stream. Those cases require attention to jq's stream semantics. The verified examples here each inspect one property of one object at a time.
Check the saved output before replacing a configuration
Write a proposed transformation to a separate file, inspect its structure and compare representative objects with the source. Do not redirect output over the input filename while the command is still reading it. A successful jq exit code means the filter ran; it does not establish that the chosen default matches the receiving application's requirements.
For a repeatable check, retain the six-case fixture alongside the filter and record your jq version. When the schema changes, add the new relevant cases rather than broadening the fallback silently. The current jq manual is the source for the operator and key-presence behavior; our small fixture shows why the policy difference affects actual output.