Conditional if/then/else for JMESPath?

4k Views Asked by At

Am trying to do a simple if/then/else using JMESPath

For example: 'if the input is a string, return the string, else return the "value" property of the input'. An input of "abc" would return "abc". An input of {"value":"def"} would return "def"

With jq this is easy: if .|type == "string" then . else .value end

With JMESPath, I can get the type

type(@)

or the input:

@

or the value property:

value

but I have not found a way to combine them into an if-then-else. Is there any way to do this?

2

There are 2 best solutions below

0
On

It is possible but not cleanly. The general form is to:

  1. Make the value you are testing an array (wrap in square braces)
  2. Apply the map function to map the filtered array to what value you want if true
  3. At this point you have an array that is populated with one (true) item if the array filter passed, otherwise it is empty
  4. Concat to that array one item (the false value)
  5. Finally, take item at index 0 in this array - which will be the result of the condition

This should allow you to also derive possible transformations for both the false and true conditions

For example, if the test data is as so:

{
   "test": 11
}

Depending on the value you can get either produce the results (using test data 11 and 2 as example):

  • "Yes, the value is 11 which is greater than 10"
  • OR
  • "No the value is 2 which is less than or equal to 10"

Like so:

[
    map(
        &join(' ', ['Yes, the value is', to_string(@), 'which is greater than 10']), 
        [test][? @ > `10`]
    ), 
    join(' ', ['No the value is', to_string(test), ' which is less than or equal to 10'])
][] | @[0]

So to abstract a template:

[
    map(
        &<True Expression Here>, 
        [<Expression you are testing>][? @ <Test Expression>]
    ), 
    <False Expression Here>)
][] | @[0]
1
On

people[?general.id !=100] || people

{
  "people": [
    {
      "general": {
        "id": 100,
        "age": 20,
        "other": "foo",
        "name": "Bob"
      },
      "history": {
        "first_login": "2014-01-01",
        "last_login": "2014-01-02"
      }
    },
    {
      "general": {
        "id": 101,
        "age": 30,
        "other": "bar",
        "name": "Bill"
      },
      "history": {
        "first_login": "2014-05-01",
        "last_login": "2014-05-02"
      }
    }
  ]
}

if else condition works here