Json Data Mapping

Hi,

I currently have a function node that maps this nasa data to an object for use later in the flow. I'm not totally happy with it because it occasionally throws an error. I could add some better error handling, but I was wondering if there was a more node-red way than a function node to convert this JSON data into an object, like so:

{
   "des":"2022 OU1",
   "orbit_id":"6",
   "jd":"2459817.400619856",
   "cd":"2022-Aug-25 21:37",
   "dist":"0.138855530107527",
   "dist_KM":"20772520",
   "dist_min":"0.13885499498311",
   "dist_max":"0.13885606523237",
   "v_rel":"7.62854662977278",
   "speed":"8km/s",
   "v_inf":"7.62603081310743",
   "t_sigma_f":"< 00:01",
   "h":"22.03",
   "size_min":"104",
   "size_max":"233"
}

Thanks for any help!

Try change node.

Realistically, there are two methods to transform one JSON structure into another:

  1. Use a change node with JSONata
  2. Use a function node.

Occasionally, you might find a (2.a) which would be to use a node.js module with a function node if you can find a module that does the bulk of the processing you want.

JSONata is great if you can work out the transform. I generally recommend giving it 10 minutes, if you haven't worked it out by then, you should go back to a function.

Oddly enough, a function node is often less processing overhead anyway.

Sometimes though, you get lucky and one of the JSONata guru's takes an interest and posts an answer :slight_smile:

Other times, not so much.

It would probably help if you showed us what the error is

Did you start by sending it through a JSON node to convert it to a JavaScript object?

Thanks, I can sort that out myself, I'm not looking for help with the function node. I'm looking to see if there is a more node-red way of doing it.

Why? The http request node can be set to output a json object.

@Ryanshafer You don't say if you parse all the arrays or if you after a specific one.
here is an example of using Javascript and JSONata to map all the values to an array of objects.

[{"id":"88aeec8c.8e386","type":"inject","z":"9a86d59e88442f2c","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"<?xml version=\"1.0\" encoding=\"utf-8\" ?> <!DOCTYPE data [  <!ELEMENT data       (parameter+)>  <!ELEMENT parameter  (name,value)>  <!ELEMENT name       (#PCDATA)>  <!ELEMENT value      (#PCDATA)> ]> <data>    <parameter>    \t<name>DB_L2174_ALARMS</name>    \t<value><![CDATA[0000000000000111000000000000000]]></value>    </parameter>    <parameter>    \t<name>DB_DEMOD_LICENCE_OPTIONS</name>    \t<value><![CDATA[1110010000000000000001000000000000000000]]></value>    </parameter>    <parameter>    \t<name>DB_DECOD_LICENCE_OPTIONS</name>    \t<value><![CDATA[0000000000000000000000000000000000000000]]></value>    </parameter>    <parameter>    \t<name>DB_DEMOD_SELFTEST_RESULTS</name>    \t<value><![CDATA[100000000000000000000000000000000]]></value>    </parameter>    <parameter>    \t<name>DB_L2174_RX_MODE</name>    \t<value><![CDATA[DVBT]]></value>    </parameter>    <parameter>    \t<name>DB_L2174_FREQ1</name>    \t<value><![CDATA[2.030000]]></value>    </parameter>    </data>","payloadType":"str","x":70,"y":300,"wires":[["e129cb3.1181238"]]},{"id":"e129cb3.1181238","type":"http request","z":"9a86d59e88442f2c","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"https://ssd-api.jpl.nasa.gov/cad.api?date-min=now&dist-max=0.2","tls":"","persist":false,"proxy":"","authType":"","x":240,"y":300,"wires":[["72662c0b.42bec4","df71d57e.fe9248"]]},{"id":"72662c0b.42bec4","type":"change","z":"9a86d59e88442f2c","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"$$.payload.data@$a.($$.payload.fields#$i.${$: $a[$i]})","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":420,"y":400,"wires":[["995d7e86.aea2f"]]},{"id":"df71d57e.fe9248","type":"function","z":"9a86d59e88442f2c","name":"","func":"msg.payload = msg.payload.data.map(arr => {\n    let obj = {};\n    msg.payload.fields.forEach((key, index) => {\n        obj[key] = arr[index];\n    })\n    return obj;\n})\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":450,"y":280,"wires":[["9e47108c.90d0f8"]]},{"id":"995d7e86.aea2f","type":"debug","z":"9a86d59e88442f2c","name":"jsonata","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":650,"y":400,"wires":[]},{"id":"9e47108c.90d0f8","type":"debug","z":"9a86d59e88442f2c","name":"javascript","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":630,"y":280,"wires":[]}]

Javascript

msg.payload = msg.payload.data.map(arr => {
    let obj = {};
    msg.payload.fields.forEach((key, index) => {
        obj[key] = arr[index];
    })
    return obj;
})
return msg;

JSONata

$$.payload.data@$a.($$.payload.fields#$i.${$: $a[$i]})

Yea, but the response from the API is designed to save space, so you get a JSON response with all the fields list once and then all the data as separate items without key/value pairs. So I have to construct the final object.

{
   "signature":{
      "source":"NASA/JPL SBDB Close Approach Data API",
      "version":"1.4"
   },
   "count":"181",
   "fields":[
      "des",
      "orbit_id",
      "jd",
      "cd",
      "dist",
      "dist_min",
      "dist_max",
      "v_rel",
      "v_inf",
      "t_sigma_f",
      "h"
   ],
   "data":[
      [
         "2022 OU1",
         "6",
         "2459817.400619856",
         "2022-Aug-25 21:37",
         "0.138855530107527",
         "0.13885499498311",
         "0.13885606523237",
         "7.62854662977278",
         "7.62603081310743",
         "< 00:01",
         "22.03"
      ]

Thanks, I'll take a look. But can the change node+JSONata iterate over hundreds of items to make one object? I haven't ever used it that way.

I'm after all of them. Thanks I'll take a look!

Yes, it can. If you have a PhD in 10 dimensional quantum physics! :slight_smile:

In other words, it is capable of it but working it out is likely to give you a splitting headache and a desire to retreat to a darkened room.

Doing it with JS is simple and almost certainly faster to write, faster to run and much easier to grok in 6 months time should you need to change it.

1 Like

Even better. I asked because the data was shown as JSON not a JavaScript object, it was not clear that the OP knew that he should start by converting it.

Yes, but knowing what the error is may be a result of variations in the data that would have an impact on what other approaches to take.