Discarding nulls - jmespath-community/jmespath.spec GitHub Wiki

Problem statement

Discarding null values is a surprisingly frequently requested feature from JMESPath. The canonical answer is to use the merge() function and let external deserializers discard / ignore those values.

That said, the items(), from_items() and zip() functions let you build primitives to achieve this.

How to

Given:

{ "a": 1, "b": "", "c": null }

The following expressions can be useful:

  • from_items( items(@) [? @[1]!=`null` ] ) returns `` { "a": 1, "b": "" }
  • from_items( items(@) [? @[1]!='' ] ) returns `` { "a": 1, "c": null }
  • from_items( items(@) [? @[1] ] ) returns `` { "a": 1 }

More complex objects

The previous primitives can be used in more complex scenarios where the discarded values are in nested object structures.

Given:

{
	"key1": { "a": 1, "b": "", "c": null },
	"key2": { "a": 2, "b": "bee", "c": "" }
}

This requires a way to split keys from their values, operate on the values using one of the primitives referred to above, and reconstruct the object.

The following expressions are needed:

  • keys(@) to extract the key from the object.
  • values(@)[*].from_items( items(@)[[email protected][1]] ) to discard all falsy values, that include both null and empty strings.

Given those two expressions, the let() function lets you create a scope to hold both keys and computed values, and operate on them using an expression-type:

let( { k:keys(@), v:values(@)[*].from_items( items(@)[[email protected][1]] ) }, &… )

The first argument to the let() function creates a multi-select-hash scope with two properties, k and v that hold the keys from the original input and the newly computed values respectively.

The second argument to the let() function is an expression-type that can be used to operate on said scope object.

To reconstruct an object from a given set of keys and values, use the following expression:

from_items( { k:k, v:v }.zip(k, v) )

Note: the let() function is currently being discussed and subject to change. However, lexical scoping using some form of a let expression will still be possible.