Skip to content

Commit b3e420c

Browse files
authored
parser json UPDATE optional JSON 'null' value parsed and ignored (#2216)
This patch introduces parsing flag, which allows user to use JSON 'null' value with leaf, leaf-list and anydata
1 parent 4601fc9 commit b3e420c

File tree

4 files changed

+29
-2
lines changed

4 files changed

+29
-2
lines changed

src/parser_data.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,8 @@ struct ly_in;
176176
be checked (length, range, pattern, ...) and if a value can be stored,
177177
it is. Calling separate validation on these data always checks all the
178178
restrictions as well. */
179+
#define LYD_PARSE_JSON_NULL 0x4000000 /**< Allow using JSON empty value 'null' within JSON input. By default such value
180+
is not supported and according to RFC 7951 '[null]' shall be used instead. */
179181

180182
#define LYD_PARSE_OPTS_MASK 0xFFFF0000 /**< Mask for all the LYD_PARSE_ options. */
181183

src/parser_json.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1492,7 +1492,10 @@ lydjson_parse_instance(struct lyd_json_ctx *lydctx, struct lyd_node *parent, str
14921492
if (r == LY_SUCCESS) {
14931493
assert(snode->nodetype & (LYD_NODE_TERM | LYD_NODE_INNER | LYD_NODE_ANY));
14941494
if (snode->nodetype & LYD_NODE_TERM) {
1495-
if ((*status != LYJSON_ARRAY) && (*status != LYJSON_NUMBER) && (*status != LYJSON_STRING) &&
1495+
if ((lydctx->parse_opts & LYD_PARSE_JSON_NULL) && (*status == LYJSON_NULL)) {
1496+
/* do not do anything if value is JSON 'null' */
1497+
goto cleanup;
1498+
} else if ((*status != LYJSON_ARRAY) && (*status != LYJSON_NUMBER) && (*status != LYJSON_STRING) &&
14961499
(*status != LYJSON_FALSE) && (*status != LYJSON_TRUE) && (*status != LYJSON_NULL)) {
14971500
rc = LY_ENOT;
14981501
goto cleanup;
@@ -1519,6 +1522,10 @@ lydjson_parse_instance(struct lyd_json_ctx *lydctx, struct lyd_node *parent, str
15191522
r = lydjson_parse_instance_inner(lydctx, snode, ext, status, node);
15201523
LY_DPARSER_ERR_GOTO(r, rc = r, lydctx, cleanup);
15211524
} else {
1525+
if ((lydctx->parse_opts & LYD_PARSE_JSON_NULL) && (*status == LYJSON_NULL)) {
1526+
/* do not do anything if value is JSON 'null' */
1527+
goto cleanup;
1528+
}
15221529
/* create any node */
15231530
r = lydjson_parse_any(lydctx, snode, ext, status, node);
15241531
LY_DPARSER_ERR_GOTO(r, rc = r, lydctx, cleanup);

tests/utests/data/test_parser_json.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,11 @@ test_leaf(void **state)
163163
data = "{\"@a:foo\":{\"a:hi\\nt\":1},\"a:foo\":\"xxx\"}";
164164
assert_int_equal(LY_EINVAL, lyd_parse_data_mem(UTEST_LYCTX, data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, &tree));
165165
CHECK_LOG_CTX("Annotation definition for attribute \"a:hi\nt\" not found.", "/@a:foo/@a:hi\nt", 1);
166+
167+
data = "{\"a:foo\": null}";
168+
PARSER_CHECK_ERROR(data, 0, LYD_VALIDATE_PRESENT, tree, LY_EVALID, "Invalid non-string-encoded string value \"\".", "/a:foo", 1);
169+
CHECK_PARSE_LYD(data, LYD_PARSE_JSON_NULL, LYD_VALIDATE_PRESENT, tree);
170+
assert_null(tree);
166171
}
167172

168173
static void
@@ -291,6 +296,11 @@ test_anydata(void **state)
291296
1, LYS_ANYDATA, 0, 0, NULL, 0);
292297
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
293298
lyd_free_all(tree);
299+
300+
data = "{\"a:any\": null}";
301+
PARSER_CHECK_ERROR(data, 0, LYD_VALIDATE_PRESENT, tree, LY_EVALID, "Expecting JSON name/object but anydata \"any\" is represented in input data as name/null.", NULL, 1);
302+
CHECK_PARSE_LYD(data, LYD_PARSE_JSON_NULL, LYD_VALIDATE_PRESENT, tree);
303+
assert_null(tree);
294304
}
295305

296306
static void

tools/lint/main_ni.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,9 @@ help(int shortout)
211211
printf(" -X, --extended-leafref\n"
212212
" Allow usage of deref() XPath function within leafref\n\n");
213213

214+
printf(" -J, --json-null\n"
215+
" Allow usage of JSON empty values ('null') within input data\n\n");
216+
214217
printf(" -G GROUPS, --debug=GROUPS\n"
215218
#ifndef NDEBUG
216219
" Enable printing of specific debugging message group\n"
@@ -463,6 +466,7 @@ fill_context(int argc, char *argv[], struct yl_opt *yo, struct ly_ctx **ctx)
463466
{"yang-library", no_argument, NULL, 'y'},
464467
{"yang-library-file", required_argument, NULL, 'Y'},
465468
{"extended-leafref", no_argument, NULL, 'X'},
469+
{"json-null", no_argument, NULL, 'J'},
466470
{"debug", required_argument, NULL, 'G'},
467471
{NULL, 0, NULL, 0}
468472
};
@@ -474,7 +478,7 @@ fill_context(int argc, char *argv[], struct yl_opt *yo, struct ly_ctx **ctx)
474478
yo->line_length = 0;
475479

476480
opterr = 0;
477-
while ((opt = getopt_long(argc, argv, "hvVQf:I:p:DF:iP:qs:neE:t:d:lL:o:O:R:myY:Xx:G:", options, &opt_index)) != -1) {
481+
while ((opt = getopt_long(argc, argv, "hvVQf:I:p:DF:iP:qs:neE:t:d:lL:o:O:R:myY:XJx:G:", options, &opt_index)) != -1) {
478482
switch (opt) {
479483
case 'h': /* --help */
480484
help(0);
@@ -654,6 +658,10 @@ fill_context(int argc, char *argv[], struct yl_opt *yo, struct ly_ctx **ctx)
654658
yo->ctx_options |= LY_CTX_LEAFREF_EXTENDED;
655659
break;
656660

661+
case 'J': /* --json-null */
662+
yo->data_parse_options |= LYD_PARSE_JSON_NULL;
663+
break;
664+
657665
case 'G': /* --debug */
658666
if (set_debug_groups(optarg, yo)) {
659667
return -1;

0 commit comments

Comments
 (0)