JSONata - $substringBefore

It has been asked in this post how to remove from an array the strings that start with a period character.

The first solution proposed is simply brilliant. It uses the array.filter() method, ES6 arrow function and a ternary operator to solve the problem perfectly, in a single line.

A second solution proposed to use a JSONata expression as follows:

[payload[$substringBefore(".")]]

I had troubles in the past to understand this jsonata function and to be honest I never got it right. I decided to submit it to testing.

I will input this array of string and check if it filters all the strings that start with dot and only them.

[ "aaa", ".bbb", "ccc", " ", "dd.d", "", "eee.", ".", "fff", ". " ]

and the result is below

It works perfectly. So another brilliant solution but hard to understand or at least not very intuitive.

I believe it works because of the sequence flattening rules that says:

An empty sequence is a sequence with no values and is considered to be 'nothing' or 'no match'. It won't appear in the output of any expression

Edit: Flow

[{"id":"f990066f.6b1e58","type":"tab","label":"Jsonata - subtringBefore","disabled":false,"info":""},{"id":"fa4c268e.83ff98","type":"inject","z":"f990066f.6b1e58","name":"Array","topic":"","payload":"[\"aaa\",\".bbb\",\"ccc\",\" \",\"dd.d\",\"\",\"eee.\",\".\",\"fff\",\". \"]","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":130,"y":80,"wires":[["c306e321.2f67f"]]},{"id":"a933db56.36c0e8","type":"debug","z":"f990066f.6b1e58","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":510,"y":80,"wires":[]},{"id":"c306e321.2f67f","type":"change","z":"f990066f.6b1e58","name":"$substringBefore","rules":[{"t":"set","p":"output","pt":"msg","to":"[payload[$substringBefore(\".\")]]","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":330,"y":80,"wires":[["a933db56.36c0e8"]]}]

.

2 Likes

I wanted to post an old flow (using the same JSONata function) that confused me but I could not find that flow.

As far as I can remember from that flow..... using $substringBefore and $substringAfter was resulting in the very same output for the very same dataset.

However, reading the documentation I finally have a clue.

Most likely I was using as the second argument (chars) a character that was not present in the dataset passed to the functions. The documentation says that in such case the function will return the first argument untouched. :man_facepalming:

$substringBefore()

Signature: $substringBefore(str, chars)

Returns the substring before the first occurrence of the character sequence chars in str . If str is not specified (i.e. this function is invoked with only one argument), then the context value is used as the value of str . If str does not contain chars , then it returns str . An error is thrown if str and chars are not strings.