(Solved) JSONata - variable to determine correct entry of an Array

#1

Hi, I have an array of objects, with an array ValTypeCat in ea. object, as follows:

[{"thing_id":"a1", "val":0, "ValTypeCat":[Off, On]},
 {"thing_id":"a2", "val":1, "ValTypeCat":[Off, On]}]

Then, with a Change node, I want to use JSONata to show the ValTypeCat array item that corresponds to the val element, ie. val=1 should have On, corresponding to the array entry 1, (vs 0).

To create the payload in the change node, from above incoming msg.payload, and then to show the 1st entry of the ValTypeCat array[0], (thus Off in above example), the following JSONata expression works:

payload.(
        { "thing_id"  : $.thing_id,
          "val"       : $.val,
          "ValTypeCat": $.ValTypeCat[0]
        }
)

But, this does not work, it brings back the full array.

payload.(
        { "thing_id"  : $.thing_id,
          "val"       : $.val,
          "ValTypeCat": $.ValTypeCat['$.val']
        }
)

Any ideas of how to do this?

1 Like

#2
payload.(
	$myval := $.val;
    { "thing_id"  : $.thing_id,
    	"val"       : $myval,
    	"ValTypeCat": $.ValTypeCat[$myval]
    }
)
0 Likes

#3

This has been the traditional way to "restructure" an array of objects -- iterate over the array and recreate the objects from the original parts...

The more modern (and perhaps simpler?) way would be to use the object transform syntax. This allows you to just modify an object (add/delete fields, or update existing fields) without affecting other parts of the incoming object(s). Something like this expression should replace the ValTypeCat array value with the string at the index # stored in val:

payload ~> | $ | { "ValTypeCat": ($val := val; ValTypeCat[$val]) } |

The syntax is reminiscent of regex pattern matching/substitution strings like m/replace this/with this/. Essentially, this expression says "for each object in the payload, update the whole object by merging in this new ValTypeCat field value". The new value has to be inside parens because it is a compound statement -- first save the index number val in variable $val, then use that index to retrieve the correct string from the array of possible strings.

Incidentally, it may be a bit cleaner to use a different field name like ValType for the indexed value -- then you can at the same time remove the original field of possible values, using this syntax:

payload ~> | $ | { "ValType": ($val := val; ValTypeCat[$val]) }, ["ValTypeCat"] |

Note the optional 2nd arg, an array of field names to removed from each object. The result now looks like this:

[
  {
    "thing_id": "a1",
    "val": 0,
    "ValType": "Off"
  },
  {
    "thing_id": "a2",
    "val": 1,
    "ValType": "On"
  }
]
2 Likes