Skip to content

Commit

Permalink
json::decode preserve line numbers if possible
Browse files Browse the repository at this point in the history
Signed-off-by: Steve Bennett <steveb@workware.net.au>
  • Loading branch information
msteveb committed Aug 28, 2024
1 parent 1092956 commit 9041509
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 2 deletions.
12 changes: 12 additions & 0 deletions jim-json.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ typedef enum {
} json_schema_t;

struct json_state {
Jim_Obj *fileNameObj;
int line;
Jim_Obj *nullObj;
const char *json;
jsmntok_t *tok;
Expand Down Expand Up @@ -219,6 +221,7 @@ json_decode_dump_value(Jim_Interp *interp, struct json_state *state, Jim_Obj *li
Jim_Obj *elem;
int len = t->end - t->start;
const char *p = state->json + t->start;
int set_source = 1;
if (t->type == JSMN_STRING) {
/* Do we need to process backslash escapes? */
if (state->need_subst == 0 && memchr(p, '\\', len) != NULL) {
Expand All @@ -227,13 +230,18 @@ json_decode_dump_value(Jim_Interp *interp, struct json_state *state, Jim_Obj *li
elem = Jim_NewStringObj(interp, p, len);
} else if (p[0] == 'n') { /* null */
elem = state->nullObj;
set_source = 0;
} else if (p[0] == 'I') {
elem = Jim_NewStringObj(interp, "Inf", -1);
} else if (p[0] == '-' && p[1] == 'I') {
elem = Jim_NewStringObj(interp, "-Inf", -1);
} else { /* number, true or false */
elem = Jim_NewStringObj(interp, p, len);
}
if (set_source) {
/* Note we need to subtract 1 because both are 1-based values */
Jim_SetSourceInfo(interp, elem, state->fileNameObj, state->line + t->line - 1);
}

Jim_ListAppendElement(interp, list, elem);
state->tok++;
Expand Down Expand Up @@ -371,6 +379,10 @@ json_decode(Jim_Interp *interp, int argc, Jim_Obj *const argv[])
Jim_SetResultString(interp, "empty JSON string", -1);
goto done;
}

/* Save any source information from the original string */
state.fileNameObj = Jim_GetSourceInfo(interp, argv[argc - 1], &state.line);

if ((tokens = json_decode_tokenize(interp, state.json, len)) == NULL) {
goto done;
}
Expand Down
16 changes: 14 additions & 2 deletions tests/json.test
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ source [file dirname [info script]]/testing.tcl
needs cmd json::decode json
needs cmd json::encode json

set json {
# Create a json string as though it was read from data.json
set json [info source {
{
"fossil":"9c65b5432e4aeecf3556e5550c338ce93fd861cc",
"timestamp":1435827337,
Expand All @@ -24,7 +25,7 @@ set json {
"tags":["trunk"]
}]
}
}}
}} data.json 1]

test json-decode-001 {top level keys} {
lsort [dict keys [json::decode $json]]
Expand Down Expand Up @@ -122,6 +123,17 @@ test json-3.4 {-index array with -schema 2} {
} "{outer {0 {key value} 1 {key2 value2}}}\
{obj outer {mixed {obj key str} {obj key2 str}}}"

test json-4.1 {source info preserved} -body {
info source [dict get [json::decode $json] fossil]
} -result {data.json 3}

test json-4.2 {source info preserved} -body {
info source [dict get [json::decode $json] procTimeUs]
} -result {data.json 6}

test json-4.3 {source info preserved} -body {
info source [dict get [lindex [dict get [json::decode $json] payload timeline] 0] comment]
} -result {data.json 17}

unset -nocomplain json

Expand Down

0 comments on commit 9041509

Please sign in to comment.