Desk Clarity

Everyday document & browser help

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.

PolicyFilterPresent falsePresent null
Use the default for false and null.enabled // trueBecomes trueBecomes true
Use the default for null or a missing propertyif .enabled == null then true else .enabled endStays falseBecomes true
Use the default only when the key is missingif has("enabled") then .enabled else true endStays falseStays 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 propertyAlternative operatorNull checkKey-presence check
Missingtruetruetrue
nulltruetruenull
falsetruefalsefalse
truetruetruetrue
0000
Empty stringEmpty stringEmpty stringEmpty 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.

Sources