mwag
mwag

Reputation: 4035

Conditional if/then/else for JMESPath?

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?

Upvotes: 4

Views: 5457

Answers (3)

Juan Miguel Torres
Juan Miguel Torres

Reputation: 1

Input

{
  "SubscriptionId": 2,
  "CustomerId": 234,
  "ShowContractIn": "Monthly",
  "AnnualCost": 1200.00,
  "MonthlyCost": 100.00 
}

Transformation

{
  ContractCost: ShowContractIn == 'Monthly' && MonthlyCost || AnnualCost
}

Output

{
  "ContractCost": 100.00
}

taken from enter link description here

Upvotes: 0

Jeremy
Jeremy

Reputation: 834

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]

Upvotes: 1

Bhargav Rao
Bhargav Rao

Reputation: 31

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

Upvotes: 2

Related Questions