Well if I were dynamically building up the JSON I would do it as text; after all that’s all JSON really is. Text can then be passed to the Get Dictionary from Input action for parsing before you start to process individual paths within Shortcuts, but in this case you’ll just be passing it directly to the web API.
Here’s a quick shortcut that takes some example JSON as text including the arrayed example from above.
The shortcut copies the text-based JSON to the clipboard and opens it in @simonbs’ app Jayson.
In that app, we can see that it recognises the text it has been passed as JSON.
We can also see that the root level media key has an array value; which was what was required for the Telegram API.
If we then navigate into the first array element (index 0), we can see that the object being passed in that element is once again JSON, and we can see the examples previously specified.
Does that help?