Skip to content

Commit fa27c14

Browse files
authored
Merge pull request #731 from indel-ag/unpackerrorkey
Unpack: include keys in type mismatch error messages
2 parents 2f33b77 + 8b2f3e0 commit fa27c14

2 files changed

Lines changed: 81 additions & 20 deletions

File tree

src/pack_unpack.c

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -468,9 +468,10 @@ static json_t *pack(scanner_t *s, va_list *ap) {
468468
}
469469
}
470470

471-
static int unpack(scanner_t *s, json_t *root, va_list *ap);
471+
static int unpack(scanner_t *s, json_t *root, va_list *ap, const char *key);
472472

473-
static int unpack_object(scanner_t *s, json_t *root, va_list *ap) {
473+
static int unpack_object(scanner_t *s, json_t *root, va_list *ap,
474+
const char *parent_key) {
474475
int ret = -1;
475476
int strict = 0;
476477
int gotopt = 0;
@@ -488,8 +489,9 @@ static int unpack_object(scanner_t *s, json_t *root, va_list *ap) {
488489
}
489490

490491
if (root && !json_is_object(root)) {
491-
set_error(s, "<validation>", json_error_wrong_type, "Expected object, got %s",
492-
type_name(root));
492+
set_error(s, "<validation>", json_error_wrong_type, "Expected object, got %s%s%s",
493+
type_name(root), parent_key ? " for key " : "",
494+
parent_key ? parent_key : "");
493495
goto out;
494496
}
495497
next_token(s);
@@ -551,7 +553,7 @@ static int unpack_object(scanner_t *s, json_t *root, va_list *ap) {
551553
}
552554
}
553555

554-
if (unpack(s, value, ap))
556+
if (unpack(s, value, ap, key))
555557
goto out;
556558

557559
hashtable_set(&key_set, key, key_len, json_null());
@@ -605,13 +607,14 @@ static int unpack_object(scanner_t *s, json_t *root, va_list *ap) {
605607
return ret;
606608
}
607609

608-
static int unpack_array(scanner_t *s, json_t *root, va_list *ap) {
610+
static int unpack_array(scanner_t *s, json_t *root, va_list *ap, const char *parent_key) {
609611
size_t i = 0;
610612
int strict = 0;
611613

612614
if (root && !json_is_array(root)) {
613-
set_error(s, "<validation>", json_error_wrong_type, "Expected array, got %s",
614-
type_name(root));
615+
set_error(s, "<validation>", json_error_wrong_type, "Expected array, got %s%s%s",
616+
type_name(root), parent_key ? " for key " : "",
617+
parent_key ? parent_key : "");
615618
return -1;
616619
}
617620
next_token(s);
@@ -656,7 +659,7 @@ static int unpack_array(scanner_t *s, json_t *root, va_list *ap) {
656659
}
657660
}
658661

659-
if (unpack(s, value, ap))
662+
if (unpack(s, value, ap, NULL))
660663
return -1;
661664

662665
next_token(s);
@@ -676,18 +679,19 @@ static int unpack_array(scanner_t *s, json_t *root, va_list *ap) {
676679
return 0;
677680
}
678681

679-
static int unpack(scanner_t *s, json_t *root, va_list *ap) {
682+
static int unpack(scanner_t *s, json_t *root, va_list *ap, const char *key) {
680683
switch (token(s)) {
681684
case '{':
682-
return unpack_object(s, root, ap);
685+
return unpack_object(s, root, ap, key);
683686

684687
case '[':
685-
return unpack_array(s, root, ap);
688+
return unpack_array(s, root, ap, key);
686689

687690
case 's':
688691
if (root && !json_is_string(root)) {
689692
set_error(s, "<validation>", json_error_wrong_type,
690-
"Expected string, got %s", type_name(root));
693+
"Expected string, got %s%s%s", type_name(root),
694+
key ? " for key " : "", key ? key : "");
691695
return -1;
692696
}
693697

@@ -724,7 +728,8 @@ static int unpack(scanner_t *s, json_t *root, va_list *ap) {
724728
case 'i':
725729
if (root && !json_is_integer(root)) {
726730
set_error(s, "<validation>", json_error_wrong_type,
727-
"Expected integer, got %s", type_name(root));
731+
"Expected integer, got %s%s%s", type_name(root),
732+
key ? " for key " : "", key ? key : "");
728733
return -1;
729734
}
730735

@@ -739,7 +744,8 @@ static int unpack(scanner_t *s, json_t *root, va_list *ap) {
739744
case 'I':
740745
if (root && !json_is_integer(root)) {
741746
set_error(s, "<validation>", json_error_wrong_type,
742-
"Expected integer, got %s", type_name(root));
747+
"Expected integer, got %s%s%s", type_name(root),
748+
key ? " for key " : "", key ? key : "");
743749
return -1;
744750
}
745751

@@ -754,7 +760,8 @@ static int unpack(scanner_t *s, json_t *root, va_list *ap) {
754760
case 'b':
755761
if (root && !json_is_boolean(root)) {
756762
set_error(s, "<validation>", json_error_wrong_type,
757-
"Expected true or false, got %s", type_name(root));
763+
"Expected true or false, got %s%s%s", type_name(root),
764+
key ? " for key " : "", key ? key : "");
758765
return -1;
759766
}
760767

@@ -769,7 +776,8 @@ static int unpack(scanner_t *s, json_t *root, va_list *ap) {
769776
case 'f':
770777
if (root && !json_is_real(root)) {
771778
set_error(s, "<validation>", json_error_wrong_type,
772-
"Expected real, got %s", type_name(root));
779+
"Expected real, got %s%s%s", type_name(root),
780+
key ? " for key " : "", key ? key : "");
773781
return -1;
774782
}
775783

@@ -784,7 +792,8 @@ static int unpack(scanner_t *s, json_t *root, va_list *ap) {
784792
case 'F':
785793
if (root && !json_is_number(root)) {
786794
set_error(s, "<validation>", json_error_wrong_type,
787-
"Expected real or integer, got %s", type_name(root));
795+
"Expected real or integer, got %s%s%s", type_name(root),
796+
key ? " for key " : "", key ? key : "");
788797
return -1;
789798
}
790799

@@ -814,7 +823,8 @@ static int unpack(scanner_t *s, json_t *root, va_list *ap) {
814823
/* Never assign, just validate */
815824
if (root && !json_is_null(root)) {
816825
set_error(s, "<validation>", json_error_wrong_type,
817-
"Expected null, got %s", type_name(root));
826+
"Expected null, got %s%s%s", type_name(root),
827+
key ? " for key " : "", key ? key : "");
818828
return -1;
819829
}
820830
return 0;
@@ -906,7 +916,7 @@ int json_vunpack_ex(json_t *root, json_error_t *error, size_t flags, const char
906916
next_token(&s);
907917

908918
va_copy(ap_copy, ap);
909-
if (unpack(&s, root, &ap_copy)) {
919+
if (unpack(&s, root, &ap_copy, NULL)) {
910920
va_end(ap_copy);
911921
return -1;
912922
}

test/suites/api/test_unpack.c

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,57 @@ static void run_tests() {
263263
json_decref(j);
264264
json_decref(j2);
265265

266+
/* invalid types in objects */
267+
j = json_pack("{si}", "bar", 42);
268+
j2 = json_pack("{ss}", "bar", "foo");
269+
if (!json_unpack_ex(j, &error, 0, "{ss}", "bar"))
270+
fail("json_unpack failed to catch invalid type in object");
271+
check_error(json_error_wrong_type, "Expected string, got integer for key bar",
272+
"<validation>", 1, 3, 3);
273+
274+
if (!json_unpack_ex(j, &error, 0, "{sn}", "bar"))
275+
fail("json_unpack failed to catch invalid type in object");
276+
check_error(json_error_wrong_type, "Expected null, got integer for key bar",
277+
"<validation>", 1, 3, 3);
278+
279+
if (!json_unpack_ex(j, &error, 0, "{sb}", "bar"))
280+
fail("json_unpack failed to catch invalid type in object");
281+
check_error(json_error_wrong_type, "Expected true or false, got integer for key bar",
282+
"<validation>", 1, 3, 3);
283+
284+
if (!json_unpack_ex(j2, &error, 0, "{si}", "bar"))
285+
fail("json_unpack failed to catch invalid type in object");
286+
check_error(json_error_wrong_type, "Expected integer, got string for key bar",
287+
"<validation>", 1, 3, 3);
288+
289+
if (!json_unpack_ex(j2, &error, 0, "{sI}", "bar"))
290+
fail("json_unpack failed to catch invalid type in object");
291+
check_error(json_error_wrong_type, "Expected integer, got string for key bar",
292+
"<validation>", 1, 3, 3);
293+
294+
if (!json_unpack_ex(j, &error, 0, "{sf}", "bar"))
295+
fail("json_unpack failed to catch invalid type in object");
296+
check_error(json_error_wrong_type, "Expected real, got integer for key bar",
297+
"<validation>", 1, 3, 3);
298+
299+
if (!json_unpack_ex(j2, &error, 0, "{sF}", "bar"))
300+
fail("json_unpack failed to catch invalid type in object");
301+
check_error(json_error_wrong_type, "Expected real or integer, got string for key bar",
302+
"<validation>", 1, 3, 3);
303+
304+
if (!json_unpack_ex(j, &error, 0, "{s[i]}", "bar"))
305+
fail("json_unpack failed to catch invalid type in object");
306+
check_error(json_error_wrong_type, "Expected array, got integer for key bar",
307+
"<validation>", 1, 3, 3);
308+
309+
if (!json_unpack_ex(j, &error, 0, "{s{si}}", "bar", "foo"))
310+
fail("json_unpack failed to catch invalid type in object");
311+
check_error(json_error_wrong_type, "Expected object, got integer for key bar",
312+
"<validation>", 1, 3, 3);
313+
314+
json_decref(j);
315+
json_decref(j2);
316+
266317
/* Array index out of range */
267318
j = json_pack("[i]", 1);
268319
if (!json_unpack_ex(j, &error, 0, "[ii]", &i1, &i2))

0 commit comments

Comments
 (0)