How to extract some properties from an array of object?

I believe that's a pretty basic question but I can't sort it out :

Given the following array :

[
   {
       "TimeStamp":"2022-03-29T10:15:00.000Z",
       "Name":"SN: 2001680707",
       "Type":"SB 3300",
       "Serial":2001680707,
       "TotalYield":228433,
       "Power":600,
       "PVOutput":1
   },
   {
       "TimeStamp":"2022-03-29T10:10:00.000Z",
       "Name":"SN: 2001680707",
       "Type":"SB 3300",
       "Serial":2001680707,
       "TotalYield":228383,
       "Power":636,
       "PVOutput":1
   }
]

I would like to create an array of object from it containing only the TimeStamp and Power keys/values :

[
    {
         "TimeStamp" : "2022-03-29T10:15:00.000Z",
         "Power" : 600
    },
    {
       "TimeStamp" : "2022-03-29T10:10:00.000Z", 
        "Power" : 636
    }
]

I particularly love Sonata which I find very elegant, but a function would suit as well :blush:

Thanks for your help,

Matthieu

Have a look at this:

[{"id":"7dd0136182e54540","type":"inject","z":"753fdb2386ae42a9","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"[    {        \"TimeStamp\":\"2022-03-29T10:15:00.000Z\",        \"Name\":\"SN: 2001680707\",        \"Type\":\"SB 3300\",        \"Serial\":2001680707,        \"TotalYield\":228433,        \"Power\":600,        \"PVOutput\":1    },    {        \"TimeStamp\":\"2022-03-29T10:10:00.000Z\",        \"Name\":\"SN: 2001680707\",        \"Type\":\"SB 3300\",        \"Serial\":2001680707,        \"TotalYield\":228383,        \"Power\":636,        \"PVOutput\":1    } ]","payloadType":"json","x":150,"y":120,"wires":[["c474eaf52ea22f1e"]]},{"id":"68f62b358958c059","type":"debug","z":"753fdb2386ae42a9","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":630,"y":120,"wires":[]},{"id":"c474eaf52ea22f1e","type":"change","z":"753fdb2386ae42a9","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"[{\t        \"TimeStamp\": payload[0].TimeStamp,\t        \"Power\": payload[0].Power\t    \t    },\t    {\t        \"TimeStamp\": payload[1].TimeStamp,\t        \"Power\": payload[1].Power\t    }\t]","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":400,"y":120,"wires":[["68f62b358958c059"]]}]
1 Like

This page explains how to get the path to object properties:
https://nodered.org/docs/user-guide/messages

Like this:
Screenshot-7

Or, if the array is of variable length, then assuming it is in msg.payload a Function node containing this should do the job

msg.payload = msg.payload.map((element) => ({TimeStamp: element.TimeStamp, Power: element.Power}))
return msg;
2 Likes

Thanks @ghayne, as @Colin guessed, my array's length is variable and therefore the obvious solution doesn't work, sorry for not mentioning it.

@Colin perfect ! I'm not fluent in Javascript. I did found the .map object but missed the element thing you used here. I'm good now, let's put some more nodes :blush:

@Colllin, I should actually have an array of arrays containing the objects.

Something like this :

[
    [
       {
         "TimeStamp" : "2022-03-29T10:15:00.000Z",
         "Power" : 600
       }
    ],
    [
       {
       "TimeStamp" : "2022-03-29T10:10:00.000Z", 
        "Power" : 636
      }
   ]
]

How would I achieve this ?

Txs

Modify @colin's code by inserting array brackets:

msg.payload = msg.payload.map((element) => ([[{TimeStamp: element.TimeStamp, Power: element.Power}]]))
return msg;
1 Like

I really must learn Javascript. Thanks @ghayne !

Does that do what you want? I would have thought you only want one set of brackets.
msg.payload = msg.payload.map((element) => ([{TimeStamp: element.TimeStamp, Power: element.Power}]))

1 Like

Exactly @Colin. I was wondering why two brackets and soon discovered that one was more than enough :wink:

1 Like

@colin, correct!

So, just for fun, any idea how to do this using Jsonata ? There is a $map() function but no idea how to use it.

[{"id":"7dd0136182e54540","type":"inject","z":"753fdb2386ae42a9","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"[    {        \"TimeStamp\":\"2022-03-29T10:15:00.000Z\",        \"Name\":\"SN: 2001680707\",        \"Type\":\"SB 3300\",        \"Serial\":2001680707,        \"TotalYield\":228433,        \"Power\":600,        \"PVOutput\":1    },    {        \"TimeStamp\":\"2022-03-29T10:10:00.000Z\",        \"Name\":\"SN: 2001680707\",        \"Type\":\"SB 3300\",        \"Serial\":2001680707,        \"TotalYield\":228383,        \"Power\":636,        \"PVOutput\":1    } ]","payloadType":"json","x":150,"y":120,"wires":[["c474eaf52ea22f1e"]]},{"id":"68f62b358958c059","type":"debug","z":"753fdb2386ae42a9","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":630,"y":120,"wires":[]},{"id":"c474eaf52ea22f1e","type":"change","z":"753fdb2386ae42a9","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"$map(\t   payload,\t   function($v,$i) {\t       [{\t           \"TimeStamp\":$v.TimeStamp,\t           \"Power\":$v.Power\t       }] \t   }\t)","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":380,"y":120,"wires":[["68f62b358958c059"]]}]
1 Like

Look here for an explanation:

If you don't know javascript of jsonata I suggest starting with javascript. Once you are proficient with that then try jsonata. I unless you have more brain power than I have anyway. For me learning one new language at a time is more than enough :slight_smile:

True. However, my brain feels more adapted to the JSONata way of doing this, probably because it's more visual (and that's also why I love coding in NodeRed). @ghayne 's solution works brilliantly by the way :

$map(
   payload,
   function($v,$i) {
       [{
           "time":$toMillis($v.TimeStamp),
           "Power":$v.Power
       }] 
   }
)

Since I asked preferably the JSONata code, I think he deserves the "solution" tag, but thank you both of you really for your support.

Matthieu

In that case by all means do that. Mine most definitely is happier with the procedural route.

2 Likes

No need to call the $map() function
This also maps

$$.payload.[{
       "TimeStamp":$toMillis($.TimeStamp),
       "Power":$.Power
}] 
2 Likes

I love jsonata so much :heart::heart::heart:

1 Like

Ah @E1cid I knew you were around somewhere :slight_smile:

1 Like