JSONata value - keyname

I have trouble with jsonata.

Given this array:

[
  {
    "_ansible_item_label": "hostname.stdout",
    "_ansible_no_log": null,
    "_ansible_verbose_always": true,
    "ansible_loop_var": "item",
    "changed": false,
    "failed": false,
    "hostname.stdout": "cinema",
    "item": "hostname.stdout"
  },
  {
    "_ansible_item_label": "uptime.stdout",
    "_ansible_no_log": null,
    "_ansible_verbose_always": true,
    "ansible_loop_var": "item",
    "changed": false,
    "failed": false,
    "item": "uptime.stdout",
    "uptime.stdout": "22 days"
  }
]

I want to get the values from the properties that are given in item.

Hardcoded I would use hostname.stdout - but this property name is not known up front, so it is very useful that it is available in the item property, but how can i dynamically get the item value and use that to read the property ? trying to use the backticks with item but that selects all 'items' as an array.

End result should become something like:

{
  "hostname": "cinema",
  "uptime": "22 days"
}

Not entirely sure if I understand your question but assuming you can use a function instead of JSONata, does this work for you?

const parentItem = data.find(e => e.item === "hostname.stdout")
const childItem = data.find(e => e.item === "uptime.stdout")
const hostname = parentItem["hostname.stdout"]
const uptime = childItem["uptime.stdout"]
msg.payload = { hostname, uptime }
return msg

Thanks, I was not sure how to formulate the question.

To rephrase it: I do not know the property name hostname.stdout upfront (it could be anything like example.stdout), but item contains the property name - the value of item describes the property name I want to read.

Ah ok, now I understand.

const data = msg.payload
const payload = {}
data.forEach(e => {
  const niceName = e.item.split('.')[0]
  payload[niceName] = e[e.item]
})
msg.payload = payload
return msg

(Untested)

The JSONata would be

$$.payload.${$split($.item, ".")[0]: $lookup($,$.item)}

output

{
    "hostname": "cinema",
    "uptime": "22 days"
}

Thanks alot indeed this is the right direction, but because I did not provide my full output thinking I could manage it, but I cannot make it work "perfectly".

The json object is much larger and the array is nested. See the output on try.jsonata

Now i have the following:

**[msg='All items completed'].[
    $.results.${$split($.item, ".")[0]: $lookup($,$.item)}
]

which produces:

[
  [
    {
      "hostname": "cinema",
      "uptime": "22 days"
    }
  ],
  [
    {
      "hostname": "homebridge",
      "uptime": "22 days"
    }
  ]
]

I would like to get rid of the surrounding arrays if possible. The "all items completed" may also not be the best thing to filter on, as I don't know what it produces when it fails at a step (yet to test). Perhaps the last element in the task array, as it will always be the last element that contains the end results of the tasks it executed (this comes from an ansible playbook btw).

@Steve-Mcl Thanks, although untested, by the looks of it this might work too, I might resort to a function node if this doesnt work out.

does this work

**[msg='All items completed'].[
    $.results.${$split($.item, ".")[0]: $lookup($,$.item)}
][[0]]

or

**[msg='All items completed'].(
    $.results.${$split($.item, ".")[0]: $lookup($,$.item)}
)

Nice the second one works perfectly, thanks!

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.