Merge pull request #263 from wking/display-first-unrecognized-key
pack_unpack: List first unrecognized key in strict unpacking
This commit is contained in:
commit
52015cf35c
@ -436,6 +436,8 @@ static int unpack_object(scanner_t *s, json_t *root, va_list *ap)
|
|||||||
if(root && strict == 1) {
|
if(root && strict == 1) {
|
||||||
/* We need to check that all non optional items have been parsed */
|
/* We need to check that all non optional items have been parsed */
|
||||||
const char *key;
|
const char *key;
|
||||||
|
int have_unrecognized_keys = 0;
|
||||||
|
strbuffer_t unrecognized_keys;
|
||||||
json_t *value;
|
json_t *value;
|
||||||
long unpacked = 0;
|
long unpacked = 0;
|
||||||
if (gotopt) {
|
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) {
|
json_object_foreach(root, key, value) {
|
||||||
if(!hashtable_get(&key_set, key)) {
|
if(!hashtable_get(&key_set, key)) {
|
||||||
unpacked++;
|
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 {
|
} 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;
|
unpacked = (long)json_object_size(root) - (long)key_set.size;
|
||||||
}
|
}
|
||||||
if (unpacked) {
|
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;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -298,10 +298,16 @@ static void run_tests()
|
|||||||
json_decref(j);
|
json_decref(j);
|
||||||
|
|
||||||
/* Unpack the same item twice */
|
/* 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))
|
if(!json_unpack_ex(j, &error, 0, "{s:s,s:s!}", "foo", &s, "foo", &s))
|
||||||
fail("json_unpack object with strict validation failed");
|
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);
|
json_decref(j);
|
||||||
|
|
||||||
j = json_pack("[i,{s:i,s:n},[i,i]]", 1, "foo", 2, "bar", 3, 4);
|
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");
|
j = json_pack("{s{snsn}}", "foo", "bar", "baz");
|
||||||
if(!json_unpack_ex(j, &error, 0, "{s{sn!}}", "foo", "bar"))
|
if(!json_unpack_ex(j, &error, 0, "{s{sn!}}", "foo", "bar"))
|
||||||
fail("json_unpack nested object with strict validation failed");
|
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);
|
json_decref(j);
|
||||||
|
|
||||||
/* Error in nested array */
|
/* Error in nested array */
|
||||||
@ -395,6 +401,6 @@ static void run_tests()
|
|||||||
i1 = i2 = i3 = 0;
|
i1 = i2 = i3 = 0;
|
||||||
if(!json_unpack_ex(j, &error, 0, "{sis?i!}", "foo", &i1, "bar", &i2))
|
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");
|
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);
|
json_decref(j);
|
||||||
}
|
}
|
||||||
|
@ -30,11 +30,22 @@
|
|||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
/* Assumes json_error_t error */
|
/* Assumes json_error_t error */
|
||||||
#define check_error(text_, source_, line_, column_, position_) \
|
#define check_errors(texts_, num_, source_, line_, column_, position_) \
|
||||||
do { \
|
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; \
|
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); \
|
exit(1); \
|
||||||
} \
|
} \
|
||||||
if(strcmp(error.source, source_) != 0) { \
|
if(strcmp(error.source, source_) != 0) { \
|
||||||
@ -61,6 +72,11 @@
|
|||||||
} while(0)
|
} 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();
|
static void run_tests();
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
Loading…
Reference in New Issue
Block a user