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";
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 struct ast_threadstorage result_buf
static const struct ast_app_option json_options[128]
static struct ast_custom_function json_decode_function
AST_MODULE_INFO_STANDARD_EXTENDED(ASTERISK_GPL_KEY, "JSON decoding 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.
char * strsep(char **str, const char *delims)
#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.
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.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str 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.
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within 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::@211 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)