Converting string payload into JSON

Hi and hope this question is not too basic for you guys.
I am stuck converting a string of values already pre-formatted into JSON

image

["DO:do000:OFF","DO:do001:OFF","DO:do002:OFF","DO:do003:OFF","DO:do004:OFF","DO:do005:OFF","DO:do006:ON","DO:do007:OFF","DI:di000:OFF","DI:di001:OFF","DI:di002:OFF","DI:di003:OFF","DI:di004:OFF","DI:di005:OFF","DI:di006:OFF","DI:di007:OFF","XX:ai000:","XX:ai001:","XX:ai002:","XX:ai003:","XX:ai004:","XX:ai005:","XX:ai006:","XX:ai007:","DV:vt000:ON","DV:vt001:OFF","DV:vt002:OFF","DV:vt003:OFF","DV:vt004:OFF","DV:vt005:OFF","DV:vt006:OFF","DV:vt007:OFF","DV:vt008:OFF","DV:vt009:OFF","DV:vt010:OFF","DV:vt011:OFF","DV:vt012:OFF","DV:vt013:OFF","DV:vt014:OFF","DV:vt015:OFF","DV:vt016:OFF","DV:vt017:OFF","DV:vt018:OFF","DV:vt019:OFF","DV:vt020:OFF","DV:vt021:OFF","DV:vt022:OFF","DV:vt023:OFF","DV:vt024:OFF","DV:vt025:OFF","DV:vt026:OFF","DV:vt027:OFF","DV:vt028:ON","DV:vt029:OFF","DV:vt030:OFF","DV:vt031:OFF","DONE"]

My desire outcome is a JSON like this:

{"do000":"OFF","do001":"OFF","do002":"OFF", etc.}

Any advise?
Thanks!

Try this in a function node:

obj = {};
var res;

msg.payload = JSON.parse(msg.payload);

msg.payload.forEach(function(item) {
    res = item.split(":");
    obj[res[1]] = res[2];
})
msg.payload = obj;

return msg;

Flow:

[{"id":"6b28c550.9aedfc","type":"inject","z":"7c6a9ec3.f1512","name":"","topic":"","payload":"[\"DO:do000:OFF\",\"DO:do001:OFF\",\"DO:do002:OFF\",\"DO:do003:OFF\",\"DO:do004:OFF\",\"DO:do005:OFF\",\"DO:do006:ON\",\"DO:do007:OFF\",\"DI:di000:OFF\",\"DI:di001:OFF\",\"DI:di002:OFF\",\"DI:di003:OFF\",\"DI:di004:OFF\",\"DI:di005:OFF\",\"DI:di006:OFF\",\"DI:di007:OFF\",\"XX:ai000:\",\"XX:ai001:\",\"XX:ai002:\",\"XX:ai003:\",\"XX:ai004:\",\"XX:ai005:\",\"XX:ai006:\",\"XX:ai007:\",\"DV:vt000:ON\",\"DV:vt001:OFF\",\"DV:vt002:OFF\",\"DV:vt003:OFF\",\"DV:vt004:OFF\",\"DV:vt005:OFF\",\"DV:vt006:OFF\",\"DV:vt007:OFF\",\"DV:vt008:OFF\",\"DV:vt009:OFF\",\"DV:vt010:OFF\",\"DV:vt011:OFF\",\"DV:vt012:OFF\",\"DV:vt013:OFF\",\"DV:vt014:OFF\",\"DV:vt015:OFF\",\"DV:vt016:OFF\",\"DV:vt017:OFF\",\"DV:vt018:OFF\",\"DV:vt019:OFF\",\"DV:vt020:OFF\",\"DV:vt021:OFF\",\"DV:vt022:OFF\",\"DV:vt023:OFF\",\"DV:vt024:OFF\",\"DV:vt025:OFF\",\"DV:vt026:OFF\",\"DV:vt027:OFF\",\"DV:vt028:ON\",\"DV:vt029:OFF\",\"DV:vt030:OFF\",\"DV:vt031:OFF\",\"DONE\"]","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":190,"y":1100,"wires":[["6f90c06.d15d84"]]},{"id":"6f90c06.d15d84","type":"function","z":"7c6a9ec3.f1512","name":"convert","func":"obj = {};\nvar res;\n\nmsg.payload = JSON.parse(msg.payload);\n\nmsg.payload.forEach(function(item) {\n    res = item.split(\":\");\n    obj[res[1]] = res[2];\n})\nmsg.payload = obj;\n\nreturn msg;","outputs":1,"noerr":0,"x":380,"y":1100,"wires":[["f4af9133.082d8"]]},{"id":"f4af9133.082d8","type":"debug","z":"7c6a9ec3.f1512","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":570,"y":1100,"wires":[]}]

Well the json node will do what you need. BUT the string you have isn’t quite what you need. However as the json node works both ways you can send in the object you want and see the string it produces.which is then the format of string you need to feed it.

Brilliant!! I am still struggling to full understand it :blush:
Thanks @cflurin

I have to point out that you asked how to convert a string to JSON, where what you were actually asking for was to convert a string to a javascript object. JSON is by definition a string representation of an object. In fact the string you started with was already JSON. @cflurin's solution converts that to a javascript object and then reconstructs the object into the structure that you were asking for.

Have a look here:

Javascript: https://www.w3schools.com/js/default.asp
JS Arrays: https://www.w3schools.com/js/js_arrays.asp
JS Objects: https://www.w3schools.com/js/js_objects.asp
JS JSON: https://www.w3schools.com/js/js_json_intro.asp

From the last one
"JSON is text, written with JavaScript object notation."
In other words it is a string (text).

Here is a simple flow showing the difference. Notice in the debug one says it is a string, the other an object

[{"id":"bb99236.fd9e86","type":"inject","z":"514a90a5.c7bae8","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":112,"y":76,"wires":[["1490be28.76ad2a"]]},{"id":"1490be28.76ad2a","type":"function","z":"514a90a5.c7bae8","name":"Generate JSON","func":"msg.payload = '{\"att1\": 7, \"att2\": \"something\"}'\nreturn msg;","outputs":1,"noerr":0,"x":302,"y":75,"wires":[["6a452754.aa84e8"]]},{"id":"b2eba379.4d6f2","type":"inject","z":"514a90a5.c7bae8","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":111,"y":138,"wires":[["366d0029.162a1"]]},{"id":"6a452754.aa84e8","type":"debug","z":"514a90a5.c7bae8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":510,"y":97,"wires":[]},{"id":"366d0029.162a1","type":"function","z":"514a90a5.c7bae8","name":"Generate Object","func":"// the above is the same as \nmsg.payload = {att1: 7, att2: \"something\"}\n// note this can also be written\n// msg.payload = {\"att1\": 7, \"att2\": \"something\"}\nreturn msg;","outputs":1,"noerr":0,"x":300,"y":137,"wires":[["6a452754.aa84e8"]]}]

As with all things node-red, there is always more than 1 way to do it... so, here is how I would do this:

After you pass the payload through a JSON node, the payload will be an array of strings (e.g. "DO:do000:OFF") -- these can be split on the ":" character, and rearranged into a single object, using a change node with this JSONata expression:

payload[$contains(':')].[$split(':')] {
    $[1]: $[2]
}

Essentially, what this expression says is "for each string in the payload array that contains a colon, split it on that colon, and build an object with keys as the second part of the split and value = the 3rd part of the split string".

You can see the expression in action inside the change node's expression tester (click the ... next to the J: input text field):

I copied your input json into the "payload" value (lower left), and the output is shown (lower right) as I'm editing the expression in the top window. Cool, eh?

JSONata is a powerful JSON manipulation language, which is not easy to understand, but well worth the time to it takes to learn, imo. I know you already have a working solution, but I just wanted to document this for any future applications...

4 Likes

Thanks shrickus, this is very elegant and works smooth!