aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPetri Lehtinen <petri@digip.org>2015-12-23 07:38:03 +0200
committerPetri Lehtinen <petri@digip.org>2015-12-23 07:38:03 +0200
commit52015cf35c516b5b83bf0ec0f4bfda3b53c19da2 (patch)
treed2a77319fd2c4918efbf51dfaa7a4606f9f28e1e
parent581d5b899c2ee881d55b48903ce42c4d72ca1abc (diff)
parent1d513d063a65b7b2cfbb042b4068728f49516df5 (diff)
downloadjansson-52015cf35c516b5b83bf0ec0f4bfda3b53c19da2.zip
jansson-52015cf35c516b5b83bf0ec0f4bfda3b53c19da2.tar.gz
jansson-52015cf35c516b5b83bf0ec0f4bfda3b53c19da2.tar.bz2
Merge pull request #263 from wking/display-first-unrecognized-key
pack_unpack: List first unrecognized key in strict unpacking
-rw-r--r--src/pack_unpack.c29
-rw-r--r--test/suites/api/test_unpack.c14
-rw-r--r--test/suites/api/util.h22
3 files changed, 57 insertions, 8 deletions
diff --git a/src/pack_unpack.c b/src/pack_unpack.c
index 2a956e4..617b3c0 100644
--- a/src/pack_unpack.c
+++ b/src/pack_unpack.c
@@ -436,6 +436,8 @@ static int unpack_object(scanner_t *s, json_t *root, va_list *ap)
if(root && strict == 1) {
/* We need to check that all non optional items have been parsed */
const char *key;
+ int have_unrecognized_keys = 0;
+ strbuffer_t unrecognized_keys;
json_t *value;
long unpacked = 0;
if (gotopt) {
@@ -443,6 +445,14 @@ static int unpack_object(scanner_t *s, json_t *root, va_list *ap)
json_object_foreach(root, key, value) {
if(!hashtable_get(&key_set, key)) {
unpacked++;
+
+ if (!have_unrecognized_keys) {
+ strbuffer_init(&unrecognized_keys);
+ have_unrecognized_keys = 1;
+ } else {
+ strbuffer_append_bytes(&unrecognized_keys, ", ", 2);
+ }
+ strbuffer_append_bytes(&unrecognized_keys, key, strlen(key));
}
}
} else {
@@ -450,7 +460,24 @@ static int unpack_object(scanner_t *s, json_t *root, va_list *ap)
unpacked = (long)json_object_size(root) - (long)key_set.size;
}
if (unpacked) {
- set_error(s, "<validation>", "%li object item(s) left unpacked", unpacked);
+ if (!gotopt) {
+ /* Find the first unrecognized key */
+ json_object_foreach(root, key, value) {
+ if(!hashtable_get(&key_set, key)) {
+ if (!have_unrecognized_keys) {
+ strbuffer_init(&unrecognized_keys);
+ have_unrecognized_keys = 1;
+ } else {
+ strbuffer_append_bytes(&unrecognized_keys, ", ", 2);
+ }
+ strbuffer_append_bytes(&unrecognized_keys, key, strlen(key));
+ }
+ }
+ }
+ set_error(s, "<validation>",
+ "%li object item(s) left unpacked: %s",
+ unpacked, strbuffer_value(&unrecognized_keys));
+ strbuffer_close(&unrecognized_keys);
goto out;
}
}
diff --git a/test/suites/api/test_unpack.c b/test/suites/api/test_unpack.c
index 6b76106..babe0dd 100644
--- a/test/suites/api/test_unpack.c
+++ b/test/suites/api/test_unpack.c
@@ -298,10 +298,16 @@ static void run_tests()
json_decref(j);
/* Unpack the same item twice */
- j = json_pack("{s:s, s:i}", "foo", "bar", "baz", 42);
+ j = json_pack("{s:s, s:i, s:b}", "foo", "bar", "baz", 42, "quux", 1);
if(!json_unpack_ex(j, &error, 0, "{s:s,s:s!}", "foo", &s, "foo", &s))
fail("json_unpack object with strict validation failed");
- check_error("1 object item(s) left unpacked", "<validation>", 1, 10, 10);
+ {
+ const char *possible_errors[] = {
+ "2 object item(s) left unpacked: baz, quux",
+ "2 object item(s) left unpacked: quux, baz"
+ };
+ check_errors(possible_errors, 2, "<validation>", 1, 10, 10);
+ }
json_decref(j);
j = json_pack("[i,{s:i,s:n},[i,i]]", 1, "foo", 2, "bar", 3, 4);
@@ -335,7 +341,7 @@ static void run_tests()
j = json_pack("{s{snsn}}", "foo", "bar", "baz");
if(!json_unpack_ex(j, &error, 0, "{s{sn!}}", "foo", "bar"))
fail("json_unpack nested object with strict validation failed");
- check_error("1 object item(s) left unpacked", "<validation>", 1, 7, 7);
+ check_error("1 object item(s) left unpacked: baz", "<validation>", 1, 7, 7);
json_decref(j);
/* Error in nested array */
@@ -395,6 +401,6 @@ static void run_tests()
i1 = i2 = i3 = 0;
if(!json_unpack_ex(j, &error, 0, "{sis?i!}", "foo", &i1, "bar", &i2))
fail("json_unpack failed for optional values with strict mode and compensation");
- check_error("1 object item(s) left unpacked", "<validation>", 1, 8, 8);
+ check_error("1 object item(s) left unpacked: baz", "<validation>", 1, 8, 8);
json_decref(j);
}
diff --git a/test/suites/api/util.h b/test/suites/api/util.h
index 1bc4c9c..ea0be34 100644
--- a/test/suites/api/util.h
+++ b/test/suites/api/util.h
@@ -30,11 +30,22 @@
} while(0)
/* Assumes json_error_t error */
-#define check_error(text_, source_, line_, column_, position_) \
+#define check_errors(texts_, num_, source_, line_, column_, position_) \
do { \
- if(strcmp(error.text, text_) != 0) { \
+ int i_, found_ = 0; \
+ for(i_ = 0; i_ < num_; i_++) { \
+ if(strcmp(error.text, texts_[i_]) == 0) { \
+ found_ = 1; \
+ break; \
+ } \
+ } \
+ if (!found_) { \
failhdr; \
- fprintf(stderr, "text: \"%s\" != \"%s\"\n", error.text, text_); \
+ if (num_ == 1) { \
+ fprintf(stderr, "text: \"%s\" != \"%s\"\n", error.text, texts_[0]); \
+ } else { \
+ fprintf(stderr, "text: \"%s\" does not match\n", error.text); \
+ } \
exit(1); \
} \
if(strcmp(error.source, source_) != 0) { \
@@ -61,6 +72,11 @@
} while(0)
+/* Assumes json_error_t error */
+#define check_error(text_, source_, line_, column_, position_) \
+ check_errors(&text_, 1, source_, line_, column_, position_)
+
+
static void run_tests();
int main() {