Skip to content

Commit

Permalink
Enable optional object/array members in json_pack()
Browse files Browse the repository at this point in the history
  • Loading branch information
npmccallum committed Apr 19, 2017
1 parent 74028ff commit 28666ce
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 2 deletions.
23 changes: 22 additions & 1 deletion doc/apiref.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1269,6 +1269,14 @@ arguments.

.. versionadded:: 2.8

``s*`` (string) [const char \*]
Like ``s``, but if the argument is *NULL*, do not output any value.
This format can only be used inside an object or an array. If used
inside an object, the corresponding key is additionally suppressed
when the value is omitted. See below for an example.

.. versionadded:: 2.11

``s#`` (string) [const char \*, int]
Convert a UTF-8 buffer of a given length to a JSON string.

Expand Down Expand Up @@ -1324,11 +1332,20 @@ arguments.
yourself.

``o?``, ``O?`` (any value) [json_t \*]
Like ``o`` and ``O?``, respectively, but if the argument is
Like ``o`` and ``O``, respectively, but if the argument is
*NULL*, output a JSON null value.

.. versionadded:: 2.8

``o*``, ``O*`` (any value) [json_t \*]
Like ``o`` and ``O``, respectively, but if the argument is
*NULL*, do not output any value. This format can only be used
inside an object or an array. If used inside an object, the
corresponding key is additionally suppressed. See below for an
example.

.. versionadded:: 2.11

``[fmt]`` (array)
Build an array with contents from the inner format string. ``fmt``
may contain objects and arrays, i.e. recursive value building is
Expand Down Expand Up @@ -1387,6 +1404,10 @@ More examples::
/* Concatenate strings together to build the JSON string "foobarbaz" */
json_pack("s++", "foo", "bar", "baz");

/* Create an empty object or array when optional members are missing */
json_pack("{s:s*,s:o*,s:O*}", "foo", NULL, "bar", NULL, "baz", NULL);
json_pack("[s*,o*,O*]", NULL, NULL, NULL);


.. _apiref-unpack:

Expand Down
19 changes: 18 additions & 1 deletion src/pack_unpack.c
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,12 @@ static json_t *pack_object(scanner_t *s, va_list *ap)
if(ours)
jsonp_free(key);

if(strchr("soO", token(s)) && s->next_token.token == '*') {
next_token(s);
next_token(s);
continue;
}

goto error;
}

Expand All @@ -249,6 +255,8 @@ static json_t *pack_object(scanner_t *s, va_list *ap)
if(ours)
jsonp_free(key);

if(strchr("soO", token(s)) && s->next_token.token == '*')
next_token(s);
next_token(s);
}

Expand All @@ -273,14 +281,23 @@ static json_t *pack_array(scanner_t *s, va_list *ap)
}

value = pack(s, ap);
if(!value)
if(!value) {
if(strchr("soO", token(s)) && s->next_token.token == '*') {
next_token(s);
next_token(s);
continue;
}

goto error;
}

if(json_array_append_new(array, value)) {
set_error(s, "<internal>", "Unable to append to array");
goto error;
}

if(strchr("soO", token(s)) && s->next_token.token == '*')
next_token(s);
next_token(s);
}
return array;
Expand Down
24 changes: 24 additions & 0 deletions test/suites/api/test_pack.c
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,18 @@ static void run_tests()
fail("json_pack object refcount failed");
json_decref(value);

/* object with optional members */
value = json_pack("{s:s,s:o,s:O}", "a", NULL, "b", NULL, "c", NULL);
if(value)
fail("json_pack object optional incorrectly succeeded");
value = json_pack("{s:**}", "a", NULL);
if(value)
fail("json_pack object optional invalid incorrectly succeeded");
value = json_pack("{s:s*,s:o*,s:O*}", "a", NULL, "b", NULL, "c", NULL);
if(!json_is_object(value) || json_object_size(value) != 0)
fail("json_pack object optional failed");
json_decref(value);

/* simple array */
value = json_pack("[i,i,i]", 0, 1, 2);
if(!json_is_array(value) || json_array_size(value) != 3)
Expand All @@ -253,6 +265,18 @@ static void run_tests()
}
json_decref(value);

/* simple array with optional members */
value = json_pack("[s,o,O]", NULL, NULL, NULL);
if(value)
fail("json_pack array optional incorrectly succeeded");
value = json_pack("[**]", NULL);
if(value)
fail("json_pack array optional invalid incorrectly succeeded");
value = json_pack("[s*,o*,O*]", NULL, NULL, NULL);
if(!json_is_array(value) || json_array_size(value) != 0)
fail("json_pack array optional failed");
json_decref(value);

/* Whitespace; regular string */
value = json_pack(" s ", "test");
if(!json_is_string(value) || strcmp("test", json_string_value(value)))
Expand Down

0 comments on commit 28666ce

Please sign in to comment.