Skip to content

Conditional Output Fields

A filter output field normally maps directly to a value in the source data. But sometimes a field should only appear — or only have a meaningful value — when a certain condition is met.

This is done with $exists() and the JSONata ternary expression.


The problem

When a shared parameter key is missing from values, reading it returns undefined in JSONata — not null. Most validators do not handle undefined the same way as null, which can produce unexpected results.

/* If the key is missing, this returns undefined — not null */
"fireRating": values.p_8fe8f5ce-4979-4679-b5e0-ccfb362b9059

The pattern: ternary with $exists

(
  $paramKey := "p_8fe8f5ce-4979-4679-b5e0-ccfb362b9059";

  $[type = "FamilySymbol"].{
    "id": id,
    "type": type,
    "name": name,
    "fireRating": $exists($lookup(values, $paramKey))
                  ? $lookup(values, $paramKey).value
                  : null
  }
)

The ternary expression:

condition ? value_if_true : value_if_false
  • If the parameter key exists → return its value (which may still be null if unset)
  • If the parameter key is missing → return null explicitly

The validator now always receives either a value or null — never undefined.


When to use this

Use conditional output fields when:

  • A shared parameter is bound to some object types but not all
  • The rule applies to a broad scope and the parameter presence varies
  • You want the validator to distinguish "no value" from "parameter not bound"

Do not use this pattern as a way to silently skip missing parameters. If the parameter should always be present on the objects in scope, filter for its existence first — see Filter if Parameter Exists.


Reading hasValue conditionally

When you need both the value and the hasValue flag in the output:

$paramKey := "p_8fe8f5ce-4979-4679-b5e0-ccfb362b9059";
$param := $lookup(values, $paramKey);

{
  "id": id,
  "fireRating": $exists($param) ? $param.value : null,
  "fireRatingHasValue": $exists($param) ? $param.hasValue : false
}

This gives the validator everything it needs to distinguish:

State fireRating fireRatingHasValue
Parameter bound, value filled "EI 30" true
Parameter bound, value empty null false
Parameter not bound null false

Note: the last two rows look identical in output. If distinguishing them matters, use Filter if Parameter Exists to restrict scope to bound parameters only.