Merge pull request #163 from vincentbernat/fix/unpack-mix-optional-and-strict
Fix unpack when mixing strict mode and optional keys
This commit is contained in:
commit
49fc6b1194
@ -350,6 +350,7 @@ static int unpack_object(scanner_t *s, json_t *root, va_list *ap)
|
||||
{
|
||||
int ret = -1;
|
||||
int strict = 0;
|
||||
int gotopt = 0;
|
||||
|
||||
/* Use a set (emulated by a hashtable) to check that all object
|
||||
keys are accessed. Checking that the correct number of keys
|
||||
@ -406,7 +407,7 @@ static int unpack_object(scanner_t *s, json_t *root, va_list *ap)
|
||||
next_token(s);
|
||||
|
||||
if(token(s) == '?') {
|
||||
opt = 1;
|
||||
opt = gotopt = 1;
|
||||
next_token(s);
|
||||
}
|
||||
|
||||
@ -432,10 +433,26 @@ static int unpack_object(scanner_t *s, json_t *root, va_list *ap)
|
||||
if(strict == 0 && (s->flags & JSON_STRICT))
|
||||
strict = 1;
|
||||
|
||||
if(root && strict == 1 && key_set.size != json_object_size(root)) {
|
||||
long diff = (long)json_object_size(root) - (long)key_set.size;
|
||||
set_error(s, "<validation>", "%li object item(s) left unpacked", diff);
|
||||
goto out;
|
||||
if(root && strict == 1) {
|
||||
/* We need to check that all non optional items have been parsed */
|
||||
const char *key;
|
||||
json_t *value;
|
||||
long unpacked = 0;
|
||||
if (gotopt) {
|
||||
/* We have optional keys, we need to iter on each key */
|
||||
json_object_foreach(root, key, value) {
|
||||
if(!hashtable_get(&key_set, key)) {
|
||||
unpacked++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* No optional keys, we can just compare the number of items */
|
||||
unpacked = (long)json_object_size(root) - (long)key_set.size;
|
||||
}
|
||||
if (unpacked) {
|
||||
set_error(s, "<validation>", "%li object item(s) left unpacked", unpacked);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
@ -378,4 +378,23 @@ static void run_tests()
|
||||
if(i1 != 42)
|
||||
fail("json_unpack failed to unpack");
|
||||
json_decref(j);
|
||||
|
||||
/* Combine ? and ! */
|
||||
j = json_pack("{si}", "foo", 42);
|
||||
i1 = i2 = 0;
|
||||
if(json_unpack(j, "{sis?i!}", "foo", &i1, "bar", &i2))
|
||||
fail("json_unpack failed for optional values with strict mode");
|
||||
if(i1 != 42)
|
||||
fail("json_unpack failed to unpack");
|
||||
if(i2 != 0)
|
||||
fail("json_unpack failed to unpack");
|
||||
json_decref(j);
|
||||
|
||||
/* But don't compensate a missing key with an optional one. */
|
||||
j = json_pack("{sisi}", "foo", 42, "baz", 43);
|
||||
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);
|
||||
json_decref(j);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user