How to use JSON_DECODE function?

I am trying to parse a JSON string returned from my API call in a dialplan.

My URL lookup returns a JSON object with the values i need for the dialplan. It’s stored in a variable an and i am trying to get values out of it

The JSON string contains a property called “option” and i am trying to get the value out of it

exten => s,n,Set(option_test=${DYNROUTE_api_result})
exten => s,n,Set(option=${JSON_DECODE(option_test,option)})

However the code above does not work.

What am i doing wrong ? What’s the right way to do this ?


There is a reason why the function takes a variable name, not the actual JSON string. You have defeated that by trying to set a variable from the actual JSON string, in preceding line.

Whilst in general, this question is unanswerable without the exact contents of the JSON string, my guess is that you will find that it contains dialplan syntax delimiter characters.

Note that, if some parts of it don’t come from a totally trustworthy source, you may have a code injection vulnerability. Thinking further, the dialplan misparses possible here may be enough to execute anything harmful.

Those are good points, thank you.

However, i thought that i had put in a variable name - option_test. I’m not sure what you mean. Can you give an example ?

Based on the small window on the code, you could use DYNROUTE_api_result directly. The bigger picture may indicate that hasn’t been handled safely either.

Using DYNROUTE_api_result directly, did not work. The string does seem to be causing some syntax errors.

Obviously, it contains “:” and “{” and “}” . but I would expect that the function should just take it in as JSON and nothing else.

Can you help me with an example ?


We’d need to see the string.

The reason that assigning to a variable could go wrong is that Asterisk dialplans are really text macros, and the values of variables are physically substituted into the dialplan line, and that is what gets parsed and passed to the application.

If you run the first version at at least verbosity 3, you should see the actual set application parameters.


That is the string returned in DYNROUTE_api_result. I thought it had some quotation marks , but it doesn’t.


Not an expert, but I believe that json strings must be enclosed in quotes, which may explain why JSON_DECODE can’t handle it.

It doesn’t explain what you’re seeing, but my own testing with Dynamic Routes and json resulted in this bug report: [FC-353] Issue with dynroutes if returned string has a " character - Sangoma Issue Tracker

1 Like

Indeed. It should look like:


This is because the dialplan interpreter is really a macro processor. The variable is substituted without reference to the quotation marks. If there is an isolated " in the variables value, the expression evaluator sees

"....."....." = ""

and thinks the = is in quotes.

Expressions are handled by a formal grammar, whereas most of the dialplan, and application arguments, is handled with more ad hoc parsing. There is is a lexical rule:

which treats any string of characters starting and ending with ", but not containing one, on a left to right scan, as being a string. Potential operator characters within one are not recognized as such.

Thanks, will try that

Thanks for the explanation

That worked, thanks

Moving on in GraphQL I now need to get a list of extensions that are logged in.

I have the following working

query {
extension {
user {



I have played in the explorer but can’t see an ext status or similar.

Extensions register to receive calls, there is no such thing as a SIP login. for chan_pjsip, that information comes under the heading of contacts. For chan_sip, it was called users.

I suspect your list of fields is taken from the FreePBX database, which is mainly used to construct the Asterisk configuration files, which are, in turn, read into memory by Asterisk. The existence of registrations is only normally recorded in memory (there may be some provision for persistence, but that is done by Asterisk, and FreePBX won’t record it).

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.