Jim Tcl
Check-in [1477093252]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:json: implement -index decode option
Timelines: family | ancestors | descendants | both | trunk |
Files: files | file ages | folders
SHA1: 1477093252ec9498f4fd481f911e9cb972f6a13f
User & Date: dbohdan@dbohdan.com 2019-11-11 05:00:23
Context
2019-11-11
21:32
configure: add SIZEOF_INT to jim-config.h

It can be useful for extensions to know the size of integers

Signed-off-by: Steve Bennett <steveb@workware.net.au> check-in: 482d1fb2ce user: steveb@workware.net.au tags: trunk,

05:00
json: implement -index decode option check-in: 1477093252 user: dbohdan@dbohdan.com tags: trunk,
2019-11-09
11:06
json: Fix decode schema for list obj

Signed-off-by: Steve Bennett <steveb@workware.net.au> check-in: 00e59d0dc4 user: steveb@workware.net.au tags: trunk,

Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to jim-json.c.

40
41
42
43
44
45
46

47
48
49
50
51
52
53
...
178
179
180
181
182
183
184




185
186
187
188
189
190
191
...
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257




258
259
260
261
262
263
264
...
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
struct json_state {
	Jim_Obj *nullObj;
	const char *json;
	jsmntok_t *tok;
	int need_subst;
	/* The following are used for -schema */
	int enable_schema;

	Jim_Obj *schemaObj;
	Jim_Obj *schemaTypeObj[JSON_MAX_TYPE];
};

static void json_decode_dump_value(Jim_Interp *interp, struct json_state *state, Jim_Obj *list);

/**
................................................................................
			if (state->enable_schema) {
				const char *p = state->json + state->tok->start;
				int len = state->tok->end - state->tok->start;
				Jim_ListAppendElement(interp, state->schemaObj, Jim_NewStringObj(interp, p, len));
			}
			json_decode_dump_value(interp, state, list);
		}





		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));
			}
		}

................................................................................
/* Parses the options ?-null string? ?-schema? *state.
 * Any options not present are not set.
 *
 * Returns JIM_OK or JIM_ERR and sets an error result.
 */
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, };
	int i;

	for (i = 1; i < argc - 1; i++) {
		int option;
		if (Jim_GetEnum(interp, argv[i], options, &option, NULL, JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) {
			return JIM_ERR;
		}
		switch (option) {




			case OPT_NULL:
				i++;
				Jim_IncrRefCount(argv[i]);
				Jim_DecrRefCount(interp, state->nullObj);
				state->nullObj = argv[i];
				break;

................................................................................
				state->enable_schema = 1;
				break;
		}
	}

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

	return JIM_OK;
}

/**







>







 







>
>
>
>







 







|
|








>
>
>
>







 







|







40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
...
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
...
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
...
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
struct json_state {
	Jim_Obj *nullObj;
	const char *json;
	jsmntok_t *tok;
	int need_subst;
	/* The following are used for -schema */
	int enable_schema;
	int enable_index;
	Jim_Obj *schemaObj;
	Jim_Obj *schemaTypeObj[JSON_MAX_TYPE];
};

static void json_decode_dump_value(Jim_Interp *interp, struct json_state *state, Jim_Obj *list);

/**
................................................................................
			if (state->enable_schema) {
				const char *p = state->json + state->tok->start;
				int len = state->tok->end - state->tok->start;
				Jim_ListAppendElement(interp, state->schemaObj, Jim_NewStringObj(interp, p, len));
			}
			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));
			}
		}

................................................................................
/* Parses the options ?-null string? ?-schema? *state.
 * Any options not present are not set.
 *
 * Returns JIM_OK or JIM_ERR and sets an error result.
 */
static int parse_json_decode_options(Jim_Interp *interp, int argc, Jim_Obj *const argv[], struct json_state *state)
{
	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++) {
		int option;
		if (Jim_GetEnum(interp, argv[i], options, &option, NULL, JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) {
			return JIM_ERR;
		}
		switch (option) {
			case OPT_INDEX:
				state->enable_index = 1;
				break;

			case OPT_NULL:
				i++;
				Jim_IncrRefCount(argv[i]);
				Jim_DecrRefCount(interp, state->nullObj);
				state->nullObj = argv[i];
				break;

................................................................................
				state->enable_schema = 1;
				break;
		}
	}

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

	return JIM_OK;
}

/**

Changes to jim_tcl.txt.

5367
5368
5369
5370
5371
5372
5373
5374
5375
5376


5377
5378
5379
5380
5381
5382
5383
5384
....
5389
5390
5391
5392
5393
5394
5395


5396
5397
5398
5399
5400
5401
5402
----

json::decode
~~~~~~~~~~~~

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

+*json::decode* ?*-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.
Decoding is as follows (with schema types listed in parentheses):
* object -> dict ('obj')
* array -> list ('mixed' or 'list')
* number -> as-is ('num')
* boolean -> as-is ('bool')
* string -> string ('str')
* null -> supplied null string or the default +'"null"'+ ('num')
................................................................................
    {1 2}
    . json::decode -schema {[1, 2]}
    {1 2} {list num}
    . json::decode -schema {{"a":1, "b":2}}
    {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}


----

[[BuiltinVariables]]
BUILT-IN VARIABLES
------------------

The following global variables are created automatically







|

|
>
>
|







 







>
>







5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
....
5391
5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
----

json::decode
~~~~~~~~~~~~

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

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

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')
* number -> as-is ('num')
* boolean -> as-is ('bool')
* string -> string ('str')
* null -> supplied null string or the default +'"null"'+ ('num')
................................................................................
    {1 2}
    . json::decode -schema {[1, 2]}
    {1 2} {list num}
    . json::decode -schema {{"a":1, "b":2}}
    {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]]
BUILT-IN VARIABLES
------------------

The following global variables are created automatically

Changes to tests/json.test.

94
95
96
97
98
99
100
























101
102
103
104
105
106
107
test json-2.8 {schema tests} {
	lindex [json::decode -schema {[1, 2, true, false]}] 1
} {mixed num num bool bool}

test json-2.9 {schema tests} {
	lindex [json::decode -schema {[{a:1},{b:2}]}] 1
} {mixed {obj a num} {obj b num}}

























unset -nocomplain json

test json-encode-1.1 {String with backslashes}  {
	json::encode {A "quoted string containing \backslashes\"}
} {"A \"quoted string containing \\backslashes\\\""}








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
test json-2.8 {schema tests} {
	lindex [json::decode -schema {[1, 2, true, false]}] 1
} {mixed num num bool bool}

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}  {
	json::encode {A "quoted string containing \backslashes\"}
} {"A \"quoted string containing \\backslashes\\\""}