From ea69c35ddd6842bca86711e504968236b70cf426 Mon Sep 17 00:00:00 2001 From: dbohdan Date: Sat, 9 Nov 2019 19:54:10 +0000 Subject: json: implement -index decode option --- jim-json.c | 15 ++++++++++++--- jim_tcl.txt | 10 +++++++--- tests/json.test | 24 ++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 6 deletions(-) diff --git a/jim-json.c b/jim-json.c index 0a47d4d..1b3869c 100644 --- a/jim-json.c +++ b/jim-json.c @@ -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]; }; @@ -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)); @@ -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++) { @@ -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]); @@ -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; } diff --git a/jim_tcl.txt b/jim_tcl.txt index 2ad1f25..01c33b4 100644 --- a/jim_tcl.txt +++ b/jim_tcl.txt @@ -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') @@ -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]] diff --git a/tests/json.test b/tests/json.test index 8dfa567..ed73401 100644 --- a/tests/json.test +++ b/tests/json.test @@ -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} { -- cgit v1.1