Check Whether a JSON Key Exists with jq

All jq tools and guides

Use has("value") to test whether an object contains a key. Accessing .value alone returns null for both an absent key and an explicit JSON null, but has returns false only when the key is absent. It still returns true when the value is null, false, 0, or "".

Check absent and present values

Save this array as input.json:

[
  {"case":"missing"},
  {"case":"null","value":null},
  {"case":"false","value":false},
  {"case":"zero","value":0},
  {"case":"empty","value":""}
]

Run this filter in the playground, or replace FILTER in jq 'FILTER' input.json with the expression below:

map({case, present: has("value"), value: .value})

Output:

[
  {
    "case": "missing",
    "present": false,
    "value": null
  },
  {
    "case": "null",
    "present": true,
    "value": null
  },
  {
    "case": "false",
    "present": true,
    "value": false
  },
  {
    "case": "zero",
    "present": true,
    "value": 0
  },
  {
    "case": "empty",
    "present": true,
    "value": ""
  }
]

Run the presence table in the jq playground

has checks the object being processed, not the value of the named field. The value column is null in the first two rows because ordinary field access cannot tell those cases apart. The present column can.

Keep records with a key, including null

Using the same input.json, select records where the key exists and return their case names:

map(select(has("value")) | .case)

Output:

["null","false","zero","empty"]

Run the presence filter in the jq playground

select(.value) would drop both null and false, even when the key exists. select(.value != null) would still drop the explicit null. Use has when your question is whether the field was supplied, rather than whether its value is usable.

These filters use core jq object syntax (jq 1.6+). Apply has to an object: for a nested field, select its parent object first and guard against a missing or non-object parent. To substitute values instead of checking presence, see handling null values and defaults; remember that // also replaces false. For other operations, see remove keys with jq and the jq cheatsheet.

Reference: jq manual: has(key).