Based on SriniV's post above, I was able to build an expression around it using the array(). As per SriniV's suggestion, it does return an array if it's already an array (so not a double or nested array), so the below step is just an extra measurement just in case it stops working.
This is the final expression:
if(startsWith(string(outputs('your_Function')?['body']), '['), outputs('your_Function')?['body'], array(outputs('your_Function')?['body']))
If you have an input for example from an Azure function then you'd need to point out to the Azure Function's body.
outputs('your_Function')?['body']
Before you start checking if it has a left square bracket "[" in order to determine if it's an array, you first need to convert it into a string because the startsWith expression can check only strings.
string(outputs('your_Function')?['body'])
Now you can wrap your string around a startsWith so you can check if it starts with a square bracket '['. This will return a true or false.
startsWith(string(outputs('your_Function')?['body']), '[')
Since you can get a true or false, now's the time to wrap it with an if expression. If it comes true as an array, then the returned output of the compose will be just the body of the function. If it's false, then the array expression will convert the output of the function into an array.
| if(startsWith(string(outputs('your_Function')?['body']), '['), outputs('your_Function')?['body'], array(outputs('your_Function')?['body'])) |
Now that you have a consistent array output, you can parse the output using a single schema. This way it saves you from building things twice depending on whether you get a single object as a result or an array.