1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

json: return errors with more context, on failed json.decode() calls.

This commit is contained in:
Delyan Angelov 2022-04-05 12:06:00 +03:00
parent 829fed4af0
commit f5e4d17cf3
No known key found for this signature in database
GPG Key ID: 66886C0F12D595ED
2 changed files with 68 additions and 3 deletions

View File

@ -69,3 +69,49 @@ fn test_skip_fields_should_be_initialised_by_json_decode() ? {
assert task.total_comments == 55
assert task.comments == []
}
//
struct DbConfig {
host string
dbname string
user string
}
fn test_decode_error_message_should_have_enough_context_empty() {
json.decode(DbConfig, '') or {
assert err.msg().len < 2
return
}
assert false
}
fn test_decode_error_message_should_have_enough_context_just_brace() {
json.decode(DbConfig, '{') or {
assert err.msg() == '{'
return
}
assert false
}
fn test_decode_error_message_should_have_enough_context_trailing_comma_at_end() {
txt := '{
"host": "localhost",
"dbname": "alex",
"user": "alex",
}'
json.decode(DbConfig, txt) or {
assert err.msg() == ' "user": "alex",\n}'
return
}
assert false
}
fn test_decode_error_message_should_have_enough_context_in_the_middle() {
txt := '{"host": "localhost", "dbname": "alex" "user": "alex", "port": "1234"}'
json.decode(DbConfig, txt) or {
assert err.msg() == 'ost", "dbname": "alex" "user":'
return
}
assert false
}

View File

@ -73,9 +73,28 @@ $dec_fn_dec {
if (!root) {
const char *error_ptr = cJSON_GetErrorPtr();
if (error_ptr != NULL) {
// fprintf(stderr, "Error in decode() for $styp error_ptr=: %s\\n", error_ptr);
// printf("\\nbad js=%%s\\n", js.str);
return (Option_$styp){.state = 2,.err = _v_error(tos2((byteptr)error_ptr)),.data = {0}};
char *prevline_ptr = (char*)error_ptr;
int maxcontext_chars = 30;
int backlines = 1;
int backchars = maxcontext_chars-7;
while(backchars--){
char prevc = *(prevline_ptr - 1);
if(0==prevc){
break;
}
if(10==prevc && !backlines--){
break;
}
prevline_ptr--;
if(123==prevc) {
break; // stop at `{` too
}
}
byte *buf = _v_malloc(maxcontext_chars + 10);
vmemset(buf, 0, maxcontext_chars+10);
vmemcpy(buf, prevline_ptr, maxcontext_chars);
// for(int x=-10;x<10;x++){ char *xx = prevline_ptr+x; fprintf(stderr, "2 prevline_ptr + %d: %p | %c | %d \\n", x, xx, (int)(*(xx)), (int)(*(xx))); } fprintf(stderr, "--------\\n");
return (Option_$styp){.state = 2,.err = _v_error(tos2(buf)),.data = {0}};
}
}
')