Functionnode - extract specific payload data

Hi!
Currently trying to wrap my head around node-red and some JS.
Using the code below I'm able to extract data from my payload.RFID and payload.Key however,
if none of these payloads exist they both return as "undefined".

var msg1 = { payload: '{"RFID": "' + msg.payload.RFID+'"}'};
var msg2 = { payload: '{"Key": "' + msg.payload.Key+'"}'};
return [ msg1, msg2 ];

How would you prevent this? I figured I could do it with an If statement, but I'm unable to find a working way to check if "msg.payload.RFID" exists?

bonusquestion:
how do I convert to json directly in the function node? I tried adding a msg3 = JSON.parse(msg1); and then returning msg3 - this didnt work. Currently just using the "json node" to fullfill this.

Attached a picture below showing the outputs, first two messages are with the payloads(correct), two last are when they don't exist(should not output anything).
nodered

Edit:
Attaching testing flow.

[{"id":"2f3e2436.82910c","type":"inject","z":"50d2c41c.c2b2fc","name":"All data","topic":"","payload":"{\"ID\": \"52 0B C6 1F\", \"Key\": \"1234\",\"RFID\": \"Mikkel\"}","payloadType":"json","repeat":"","crontab":"","once":false,"x":334,"y":167,"wires":[["5a916d21.8495f4"]]},{"id":"1658c707.976409","type":"debug","z":"50d2c41c.c2b2fc","name":"","active":true,"console":"false","complete":"true","x":1159,"y":137,"wires":[]},{"id":"5a916d21.8495f4","type":"function","z":"50d2c41c.c2b2fc","name":"","func":"key = msg.payload.Key\nrfid = msg.payload.RFID\n\n\nvar msg1 = { payload: {RFID: rfid}};\nmsg2 = { payload: {Key: key}};\nreturn [ msg1, msg2 ];","outputs":"2","noerr":0,"x":631,"y":168,"wires":[["1658c707.976409"],["deaa75af.4cbcd8"]]},{"id":"deaa75af.4cbcd8","type":"debug","z":"50d2c41c.c2b2fc","name":"","active":true,"console":"false","complete":"true","x":1136,"y":197,"wires":[]},{"id":"c4e4ea60.eceda8","type":"inject","z":"50d2c41c.c2b2fc","name":"No RFID","topic":"","payload":"{\"ID\": \"52 0B C6 1F\", \"Key\": \"1234\"}","payloadType":"json","repeat":"","crontab":"","once":false,"x":326,"y":211,"wires":[["5a916d21.8495f4"]]},{"id":"ee0c9741.31c8f8","type":"inject","z":"50d2c41c.c2b2fc","name":"Neither key nor RFID","topic":"","payload":"{\"ID\": \"52 0B C6 1F\"}","payloadType":"json","repeat":"","crontab":"","once":false,"x":288,"y":249,"wires":[["5a916d21.8495f4"]]}]

Would this work ?


m = msg.payload

if(m.hasOwnProperty("RFID")){
    
    rfid = msg.payload.RFID
    key = msg.payload.Key
    
    mgs1 = { payload: '{"RFID": "' +rfid+'"}'};
    msg2 = { payload: '{"Key": "' + key+'"}'};
    
    return [ msg1, msg2 ]; 
}

You should be able to use JSON.parse but not as you describe it, you still would need a payload property.
ie. msg3 = { payload: JSON.parse(msg1) }

If you don't want these message payloads to be JSON strings, then don't create them as JSON strings. Instead of doing:

 mgs1 = { payload: '{"RFID": "' +rfid+'"}'};
 msg2 = { payload: '{"Key": "' + key+'"}'};

you can do:

 mgs1 = { payload: {RFID: rfid} };
 msg2 = { payload: {Key: key}};

And then there is no need to JSON.parse anything.

2 Likes

Curious why you are outputting 2 separate messages. Can't you just use one msg output?


var rfid = xxxxx;//set me
var key = zzzz;//set me
var mgs1 = { payload: {
    RFID: rfid,
    Key: key
  } 
};
return msg1;

That way, one msg is produced and you can access msg.payload.rfid and msg.payload.key at the same time in the same function/node.

@bakman2
I cant seem to get your code to work, even after fiddling around with it.

Nothing is being returned (sent), So I'm guessing the "hasOwnProperty() doesn't work as expected

@Steve-Mcl
They're used later on a dashboard and sent to SQL which one was the last entry. This also means
that they aren't always sent together, so sometimes RFID alone, vice versa.
Just felt easier to split them here.

Still having issues that if neither of these objects(?) exist they will output "undefined" as payload, and this is then being sent.
I'm using a change node with ISNULL to >, but I'd like to see no output from the function node, if neither RFID or Key exists.

This works wonders - Thank you!

Still having issues with the "undefined" messages being sent tho.

mgs1 = { payload: {RFID: rfid} };
msg2 = { payload: {Key: key}};

if(rfid){
  node.send([msg1,null])
}

if(key){
  node.send([null,msg2])
}

But you don't really need to send them out of separate pins.

If you use just one output on the function node then...

if(rfid){
  node.send({ payload: {RFID: rfid}})
}

if(key){
  node.send({ payload: {Key: key}})
}

Many ways to skin this cat

Oh obviously - way easier than I made it..

I came up with this before your code (yours look simpler tho)
Is there any explanation to why it saves the messages if I don't declare msg1 and 2?
(send a payload with both, turns out fine. Send a payload with only one, they both still show up. If you declare msg1&2 this doesn't happen)
I thought node-red didn't save any data per default?

var msg1
var msg2

if (msg.payload){

if (msg.payload.hasOwnProperty("RFID")){
    RFid = msg.payload.RFID;
    msg1 = { payload: {RFID: RFid}};
}
if (msg.payload.hasOwnProperty("Key")){
    key = msg.payload.Key;
    msg2 = { payload: {Key: key}};
}
return [msg1, msg2];
}

Not sure but if you stick with your code I'd do the following...

var msg1, msg2;

if (msg.payload){
  if (msg.payload.RFID)){
    msg1 = { payload: {RFID: msg.payload.RFID}};
  }
  if (msg.payload.Key){
    msg2 = { payload: {Key: msg.payload.Key}};
  }
  return [msg1, msg2];
}
2 Likes