95#define MAX_JSON_STACK 32 
   97static int parse_node(
char **key, 
char *currentkey, 
char *nestchar, 
int count, 
struct ast_json *json, 
char *
buf, 
size_t len, 
int *depth)
 
  110    snprintf(
buf, 
len, 
"%s", 
""); 
 
  112        ast_debug(1, 
"Could not find key '%s' in parsed JSON\n", currentkey);
 
  117        unsigned long int size;
 
  128            ast_debug(1, 
"Got JSON integer: %d\n", r);
 
  129            snprintf(
buf, 
len, 
"%d", r); 
 
  134            snprintf(
buf, 
len, 
"%.17g", 
d); 
 
  138            previouskey = currentkey;
 
  139            currentkey = 
strsep(key, nestchar); 
 
  141            ast_debug(1, 
"Parsed JSON array of size %lu, key: %s\n", size, currentkey);
 
  144                    ast_debug(1, 
"No key on which to index in the array, so returning count: %lu\n", size);
 
  145                    snprintf(
buf, 
len, 
"%lu", size);
 
  149                    ast_debug(1, 
"No key on which to index in the array, so dumping '%s' array\n", previouskey);
 
  154                ast_debug(1, 
"Requested index '%s' is not numeric or is invalid\n", currentkey);
 
  155            } 
else if (r >= size) {
 
  156                ast_debug(1, 
"Requested index '%d' does not exist in parsed array\n", r);
 
  158                ast_debug(1, 
"Recursing on index %d in array\n", r);
 
  167            ast_debug(1, 
"Got JSON %s for key %s\n", r ? 
"true" : 
"false", currentkey);
 
  168            snprintf(
buf, 
len, 
"%d", r); 
 
  171            ast_debug(1, 
"Got JSON null for key %s\n", currentkey);
 
  174            ast_debug(1, 
"Got generic JSON object for key %s\n", currentkey);
 
  175            previouskey = currentkey;
 
  176            currentkey = 
strsep(key, nestchar); 
 
  182                ast_debug(1, 
"Recursing on object (key was '%s' and is now '%s')\n", previouskey, currentkey);
 
 
  200    char *nestchar = 
"."; 
 
  201    int index, res, depth = 0;
 
  209    char *varsubst, *key, *currentkey, *nextkey, *firstkey, *tmp;
 
  233        int seplen = strlen(
args.nestchar);
 
  235            ast_log(
LOG_WARNING, 
"Nesting separator '%s' has length %d and is invalid (must be a single character)\n", 
args.nestchar, seplen);
 
  237            nestchar = 
args.nestchar;
 
  246    sprintf(varsubst, 
"${%s}", 
args.varname); 
 
  249    ast_debug(1, 
"Parsing JSON using nesting delimeter '%s'\n", nestchar);
 
  252        ast_debug(1, 
"Variable '%s' contains no data, nothing to search!\n", 
args.varname);
 
  259    tmp = strstr(firstkey, nestchar);
 
  271        ast_debug(1, 
"JSON node '%s', contains no data, nothing to search!\n", currentkey);
 
  282    nextkey = 
strsep(&key, nestchar);
 
  287            ast_debug(1, 
"Requested index '%s' is not numeric or is invalid\n", currentkey);
 
 
  299    .
name = 
"JSON_DECODE",
 
 
  311        {
"{\"myboolean\": true, \"state\": \"USA\"}", 
"", 
"myboolean", 
"1"},
 
  312        {
"{\"myboolean\": false, \"state\": \"USA\"}", 
"", 
"myboolean", 
"0"},
 
  313        {
"{\"myreal\": 1E+2, \"state\": \"USA\"}", 
"", 
"myreal", 
"100"},
 
  314        {
"{\"myreal\": 1.23, \"state\": \"USA\"}", 
"", 
"myreal", 
"1.23"},
 
  315        {
"{\"myarray\": [[1]], \"state\": \"USA\"}", 
"", 
"myarray.0.0", 
"1"},
 
  316        {
"{\"myarray\": [null], \"state\": \"USA\"}", 
"", 
"myarray.0", 
""},
 
  317        {
"{\"myarray\": [0, 1], \"state\": \"USA\"}", 
"", 
"myarray", 
"[0,1]"},
 
  318        {
"[0, 1]", 
"", 
"", 
""},
 
  319        {
"[0, 1]", 
"", 
"0", 
"0"},
 
  320        {
"[0, 1]", 
"", 
"foo", 
""},
 
  321        {
"{\"mynull\": null, \"state\": \"USA\"}", 
"", 
"mynull", 
""},
 
  322        {
"{\"city\": \"Anytown\", \"state\": \"USA\"}", 
"", 
"city", 
"Anytown"},
 
  323        {
"{\"city\": \"Anytown\", \"state\": \"USA\"}", 
"", 
"state", 
"USA"},
 
  324        {
"{\"city\": \"Anytown\", \"state\": \"USA\"}", 
"", 
"blah", 
""},
 
  325        {
"{\"key1\": \"123\", \"key2\": \"456\"}", 
"", 
"key1", 
"123"},
 
  326        {
"{\"key1\": 123, \"key2\": 456}", 
"", 
"key1", 
"123"},
 
  327        {
"{ \"path\": { \"to\": { \"elem\": \"someVar\" } } }", 
"/", 
"path/to/elem", 
"someVar"},
 
  328        {
"{ \"path\": { \"to\": { \"elem\": \"someVar\" } } }", 
"", 
"path.to.elem2", 
""},
 
  329        {
"{ \"path\": { \"to\": { \"arr\": [ \"item0\", \"item1\" ] } } }", 
"/", 
"path/to/arr/2", 
""}, 
 
  330        {
"{ \"path\": { \"to\": { \"arr\": [ \"item0\", \"item1\" ] } } }", 
"/", 
"path/to/arr/-1", 
""}, 
 
  331        {
"{ \"path\": { \"to\": { \"arr\": [ \"item0\", \"item1\" ] } } }", 
"/", 
"path/to/arr/test", 
""}, 
 
  332        {
"{ \"path\": { \"to\": { \"arr\": [ \"item0\", \"item1\" ] } } }", 
"", 
"path.to.arr.test.test2.subkey", 
""}, 
 
  333        {
"{ \"path\": { \"to\": { \"arr\": [ \"item0\", \"item1\" ] } } }", 
",c", 
"path.to.arr", 
"2"}, 
 
  334        {
"{ \"path\": { \"to\": { \"arr\": [ \"item0\", \"item1\" ] } } }", 
"", 
"path.to.arr", 
"[\"item0\",\"item1\"]"},
 
  335        {
"{ \"path\": { \"to\": { \"arr\": [ \"item0\", \"item1\" ] } } }", 
".", 
"path.to.arr.1", 
"item1"},
 
  336        {
"{ \"path\": { \"to\": { \"arr\": [ \"item0\", \"item1\" ] } } }", 
"/", 
"path/to/arr", 
"[\"item0\",\"item1\"]"},
 
  337        {
"{ \"path\": { \"to\": { \"arr\": [ \"item0\", \"item1\" ] } } }", 
"/", 
"path/to/arr/1", 
"item1"},
 
  338        {
"{ \"path\": { \"to\": { \"arr\": [ {\"name\": \"John Smith\", \"phone\": \"123\"}, {\"name\": \"Jane Doe\", \"phone\": \"234\"} ] } } }", 
",c", 
"path.to.arr.0.name", 
"John Smith"},
 
  339        {
"{ \"path\": { \"to\": { \"arr\": [ {\"name\": 1, \"phone\": 123}, {\"name\": 2, \"phone\": 234} ] } } }", 
",c", 
"path.to.arr.0.name", 
"1"},
 
  340        {
"{ \"path\": { \"to\": { \"arr\": [ {\"name\": [ \"item11\", \"item12\" ], \"phone\": [ \"item13\", \"item14\" ]}, {\"name\": [ \"item15\", \"item16\" ], \"phone\": [ \"item17\", \"item18\" ]} ] } } }", 
",c", 
"path.to.arr.0.name.1", 
"item12"},
 
  341        {
"{ \"startId\": \"foobar\", \"abcd\": { \"id\": \"abcd\", \"type\": \"EXT\" }, \"bcde\": { \"id\": \"bcde\", \"type\": \"CONDITION\" }, \"defg\": { \"id\": \"defg\", \"type\": \"EXT\" }, \"efgh\": { \"id\": \"efgh\", \"type\": \"VOICEMAIL\" } }", 
"", 
"bcde", 
"{\"id\":\"bcde\",\"type\":\"CONDITION\"}"},
 
  346        info->name = 
"func_JSON_DECODE";
 
  347        info->category = 
"/funcs/func_json/";
 
  348        info->summary = 
"Test JSON_DECODE function";
 
  349        info->description = 
"Verify JSON_DECODE behavior";
 
char * strsep(char **str, const char *delims)
Asterisk main include file. File version handling, generic pbx functions.
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
#define ast_strdupa(s)
duplicate a string in memory from the stack
General Asterisk PBX channel definitions.
struct varshead * ast_channel_varshead(struct ast_channel *chan)
struct ast_channel * ast_channel_release(struct ast_channel *chan)
Unlink and release reference to a channel.
#define ast_dummy_channel_alloc()
Create a fake channel structure.
#define ast_var_assign(name, value)
Conversion utility functions.
int ast_str_to_int(const char *str, int *res)
Convert the given string to a signed integer.
static const struct ast_app_option json_options[128]
static struct ast_custom_function json_decode_function
static int load_module(void)
static int unload_module(void)
static int json_decode_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
static int parse_node(char **key, char *currentkey, char *nestchar, int count, struct ast_json *json, char *buf, size_t len, int *depth)
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
Application convenience functions, designed to give consistent look and feel to Asterisk apps.
#define AST_APP_ARG(name)
Define an application argument.
#define AST_APP_OPTIONS(holder, options...)
Declares an array of options for an application.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
#define AST_APP_OPTION(option, flagno)
Declares an application option that does not accept an argument.
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
#define ast_debug(level,...)
Log a DEBUG message.
enum ast_json_type ast_json_typeof(const struct ast_json *value)
Get the type of value.
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
void ast_json_free(void *p)
Asterisk's custom JSON allocator. Exposed for use by unit tests.
struct ast_json * ast_json_array_get(const struct ast_json *array, size_t index)
Get an element from an array.
#define ast_json_dump_string(root)
Encode a JSON value to a compact string.
struct ast_json * ast_json_load_str(const struct ast_str *input, struct ast_json_error *error)
Parse ast_str into a JSON object or array.
const char * ast_json_string_get(const struct ast_json *string)
Get the value of a JSON string.
struct ast_json * ast_json_object_get(struct ast_json *object, const char *key)
Get a field from a JSON object.
intmax_t ast_json_integer_get(const struct ast_json *integer)
Get the value from a JSON integer.
int ast_json_is_object(const struct ast_json *value)
Check if value is JSON object.
int ast_json_is_true(const struct ast_json *value)
Check if value is JSON true.
size_t ast_json_array_size(const struct ast_json *array)
Get the size of a JSON array.
double ast_json_real_get(const struct ast_json *real)
Get the value from a JSON real number.
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Asterisk module definitions.
#define ASTERISK_GPL_KEY
The text the key() function should return.
#define AST_MODULE_INFO_STANDARD_EXTENDED(keystr, desc)
Core PBX routines and definitions.
void ast_str_substitute_variables(struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ)
#define ast_custom_function_register(acf)
Register a custom function.
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
size_t attribute_pure ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
static force_inline int attribute_pure ast_strlen_zero(const char *s)
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
char *attribute_pure ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
struct ast_str * ast_str_thread_get(struct ast_threadstorage *ts, size_t init_len)
Retrieve a thread locally stored dynamic string.
Main Channel structure associated with a channel.
Data structure associated with a custom dialplan function.
Structure used to handle boolean flags.
Abstract JSON element (object, array, string, int, ...).
Support for dynamic strings.
struct ast_var_t::@224 entries
#define AST_TEST_REGISTER(cb)
#define ast_test_status_update(a, b, c...)
#define AST_TEST_UNREGISTER(cb)
#define AST_TEST_DEFINE(hdr)
#define AST_THREADSTORAGE(name)
Define a thread storage variable.
#define ast_test_flag(p, flag)