Skip to content

Commit

Permalink
json: implement -index decode option
Browse files Browse the repository at this point in the history
  • Loading branch information
dbohdan committed Nov 11, 2019
1 parent 7bb4dff commit ea69c35
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 6 deletions.
15 changes: 12 additions & 3 deletions jim-json.c
Expand Up @@ -44,6 +44,7 @@ struct json_state {
int need_subst;
/* The following are used for -schema */
int enable_schema;
int enable_index;
Jim_Obj *schemaObj;
Jim_Obj *schemaTypeObj[JSON_MAX_TYPE];
};
Expand Down Expand Up @@ -183,6 +184,10 @@ json_decode_dump_container(Jim_Interp *interp, struct json_state *state)
json_decode_dump_value(interp, state, list);
}

if (state->enable_index && type == JSMN_ARRAY) {
Jim_ListAppendElement(interp, list, Jim_NewIntObj(interp, i));
}

if (state->schemaObj && container_type != JSON_LIST) {
if (state->tok->type == JSMN_STRING || state->tok->type == JSMN_PRIMITIVE) {
json_decode_add_schema_type(interp, state, json_decode_get_type(state->tok, state->json));
Expand Down Expand Up @@ -245,8 +250,8 @@ json_decode_dump_value(Jim_Interp *interp, struct json_state *state, Jim_Obj *li
*/
static int parse_json_decode_options(Jim_Interp *interp, int argc, Jim_Obj *const argv[], struct json_state *state)
{
static const char * const options[] = { "-null", "-schema", NULL };
enum { OPT_NULL, OPT_SCHEMA, };
static const char * const options[] = { "-index", "-null", "-schema", NULL };
enum { OPT_INDEX, OPT_NULL, OPT_SCHEMA, };
int i;

for (i = 1; i < argc - 1; i++) {
Expand All @@ -255,6 +260,10 @@ static int parse_json_decode_options(Jim_Interp *interp, int argc, Jim_Obj *cons
return JIM_ERR;
}
switch (option) {
case OPT_INDEX:
state->enable_index = 1;
break;

case OPT_NULL:
i++;
Jim_IncrRefCount(argv[i]);
Expand All @@ -270,7 +279,7 @@ static int parse_json_decode_options(Jim_Interp *interp, int argc, Jim_Obj *cons

if (i != argc - 1) {
Jim_WrongNumArgs(interp, 1, argv,
"?-null nullvalue? ?-schema? json");
"?-index? ?-null nullvalue? ?-schema? json");
return JIM_ERR;
}

Expand Down
10 changes: 7 additions & 3 deletions jim_tcl.txt
Expand Up @@ -5371,10 +5371,12 @@ json::decode

The JSON -> Tcl decoder is part of the optional 'json' package.

+*json::decode* ?*-null* 'string'? ?*-schema*? 'json-string'+::
+*json::decode* ?*-index*? ?*-null* 'string'? ?*-schema*? 'json-string'+::

Decodes the given JSON string (must be array or object) into a Tcl data structure. If '+-schema+' is specified, returns a
list of +'{data schema}'+ where the schema is compatible with `json::encode`. Otherwise just returns the data.
Decodes the given JSON string (must be array or object) into a Tcl data structure. If '+-index+' is specified,
decodes JSON arrays as dictionaries with numeric keys. This makes it possible to retrieve data from nested
arrays and dictionaries with just '+dict get+'. With the option '+-schema+' returns a list of +'{data schema}'+
where the schema is compatible with `json::encode`. Otherwise just returns the data.
Decoding is as follows (with schema types listed in parentheses):
* object -> dict ('obj')
* array -> list ('mixed' or 'list')
Expand All @@ -5393,6 +5395,8 @@ Decoding is as follows (with schema types listed in parentheses):
{a 1 b 2} {obj a num b num}
. json::decode -schema {[1, 2, {a:"b", c:false}, "hello"]}
{1 2 {a b c false} hello} {mixed num num {obj a str c bool} str}
. json::decode -index {["foo", "bar"]}
{0 foo 1 bar}
----

[[BuiltinVariables]]
Expand Down
24 changes: 24 additions & 0 deletions tests/json.test
Expand Up @@ -99,6 +99,30 @@ test json-2.9 {schema tests} {
lindex [json::decode -schema {[{a:1},{b:2}]}] 1
} {mixed {obj a num} {obj b num}}


test json-3.1 {-index array} {
json::decode -index \
{[null, 1, 2, true, false, "hello"]}
} {0 null 1 1 2 2 3 true 4 false 5 hello}

test json-3.2 {-index array and object} {
json::decode -index \
{{"outer": [{"key": "value"}, {"key2": "value2"}]}}
} {outer {0 {key value} 1 {key2 value2}}}

test json-3.3 {-index array with -schema} {
json::decode -index -schema \
{[null, 1, 2, true, false, "hello"]}
} "{0 null 1 1 2 2 3 true 4 false 5 hello}\
{mixed num num num bool bool str}"

test json-3.4 {-index array with -schema 2} {
json::decode -index -schema \
{{"outer": [{"key": "value"}, {"key2": "value2"}]}}
} "{outer {0 {key value} 1 {key2 value2}}}\
{obj outer {mixed {obj key str} {obj key2 str}}}"


unset -nocomplain json

test json-encode-1.1 {String with backslashes} {
Expand Down

0 comments on commit ea69c35

Please sign in to comment.