Selecting an object from within an object

In a flow, I have a msg payload object similar to;

{
    "a2c61946a883218c": {
        "online": true,
        "status": "on",
        "name": "sensor1"
    },
    "a2c61946a883443c": {
        "online": true,
        "status": "off",
        "name": "sensor2"
    },
    "a2c61946a765218c": {
        "online": false,
        "status": "on",
        "name": "sensor3"
    }
}

I would like to retrieve the object that contains a specific value in the key name.
So for example, if I wanted sensor2, it would produce a payload output;

{
     "online": true,
     "status": "off",
     "name": "sensor2"
}

The node producing the flow may not include the value (sensor2) at all, or may produce an object with a different format, in which cases I would expect no match, and therefore no output. Also the position of "name": "sensor2" may not be in the same order within the objects.

I've been tying by using Object.entries but failing so far...

You could use something like:

let obj = msg.payload
let filtered = Object.entries(obj).filter(x => x[1].name === "sensor1")
msg.filtered = filtered
return msg;

output:

{  "filtered": [
    [
      "a2c61946a883218c",
      {
        "online": true,
        "status": "on",
        "name": "sensor1"
      }
    ]}
1 Like

If you are just wanting to replace the payload with a single object having that specific name, you can use the JSONata expression payload.*[name="sensor2"] in a change node.

To use another field (e.g. 'topic') as the lookup key, try payload.*[name=$$.topic] -- the $$. prefix in this case is necessary in order to reset the context to look for the topic field in the root of the msg object.

3 Likes

find() will find the first match
e.g

let filtered = Object.values(msg.payload).find(value => value.name === "sensor1");
msg.payload = filtered;
return msg;

Output

{
"online":true,
"status":"on",
"name":"sensor1"
}
1 Like

@E1cid Thanks, this produces the output format exactly how I want it.
The only slight problem is that in the cases where;

...the code produces a 'undefined' payload, so is it a case of adding something like;

if (filtered != undefined) {
msg.payload = filtered;
node.send(msg);
}

try this

let filtered = Object.values(msg.payload).find(value => value.name === "sensor1");
msg.payload = filtered;
if(msg.payload === undefined) msg = null;
return msg;

or

let filtered = Object.values(msg.payload).find(value => value.name === "sensor1");
msg = filtered === undefined ? null : {payload:filtered};
return msg;
2 Likes

Thanks, that's better than my effort!

@bakman2 @shrickus Thanks for helping.

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