json empty type null encoded as [null]

This commit is contained in:
Olof hagsand 2019-07-29 15:14:24 +02:00
parent 3b93c812d4
commit d7a8cf5b0c
4 changed files with 35 additions and 24 deletions

View file

@ -27,8 +27,10 @@
* JSON changes * JSON changes
* Non-pretty-print output removed all extra spaces. * Non-pretty-print output removed all extra spaces.
* Example: `{"nacm-example:x": 42}` --> {"nacm-example:x":42}` * Example: `{"nacm-example:x": 42}` --> {"nacm-example:x":42}`
* Empty JSON container changed from `null` to `{}`. * Empty JSON values changed from `null` to:
* Empty list and leafs remain as `null` * Empty yang container encoded as `{}`
* Empty leaf/leaf-list of type empty encoded as `[null]`
* Other empty values remain as `null`
### Minor changes ### Minor changes
* Removed unnecessary configure dependencies * Removed unnecessary configure dependencies

View file

@ -196,7 +196,6 @@ api_data_get2(clicon_handle h,
cbuf_free(ccc); cbuf_free(ccc);
} }
#endif #endif
if (xml2json_cbuf(cbx, xret, pretty) < 0) if (xml2json_cbuf(cbx, xret, pretty) < 0)
goto done; goto done;
} }

View file

@ -193,14 +193,14 @@ array_eval(cxobj *xprev,
char *ns2; char *ns2;
nsx = xml_find_type_value(x, NULL, "xmlns", CX_ATTR); nsx = xml_find_type_value(x, NULL, "xmlns", CX_ATTR);
if (xml_type(x)!=CX_ELMNT){ if (xml_type(x) != CX_ELMNT){
array=BODY_ARRAY; array=BODY_ARRAY;
goto done; goto done;
} }
ys = xml_spec(x); ys = xml_spec(x);
if (xnext && if (xnext &&
xml_type(xnext)==CX_ELMNT && xml_type(xnext)==CX_ELMNT &&
strcmp(xml_name(x),xml_name(xnext))==0){ strcmp(xml_name(x), xml_name(xnext))==0){
ns2 = xml_find_type_value(xnext, NULL, "xmlns", CX_ATTR); ns2 = xml_find_type_value(xnext, NULL, "xmlns", CX_ATTR);
if ((!nsx && !ns2) if ((!nsx && !ns2)
|| (nsx && ns2 && strcmp(nsx,ns2)==0)) || (nsx && ns2 && strcmp(nsx,ns2)==0))
@ -420,13 +420,17 @@ json2xml_decode(cxobj *x,
if (keyword == Y_LEAF || keyword == Y_LEAF_LIST){ if (keyword == Y_LEAF || keyword == Y_LEAF_LIST){
if (yang_type_get(y, NULL, &ytype, NULL, NULL, NULL, NULL, NULL) < 0) if (yang_type_get(y, NULL, &ytype, NULL, NULL, NULL, NULL, NULL) < 0)
goto done; goto done;
if (ytype)
if (ytype){
if (strcmp(yang_argument_get(ytype),"identityref")==0){ if (strcmp(yang_argument_get(ytype),"identityref")==0){
if ((ret = json2xml_decode_identityref(x, y, xerr)) < 0) if ((ret = json2xml_decode_identityref(x, y, xerr)) < 0)
goto done; goto done;
if (ret == 0) if (ret == 0)
goto fail; goto fail;
} }
else if (strcmp(yang_argument_get(ytype), "empty")==0)
; /* dont need to do anything */
}
} }
} }
xc = NULL; xc = NULL;
@ -464,6 +468,7 @@ xml2json_encode_identityref(cxobj *xb,
yang_stmt *yspec; yang_stmt *yspec;
yang_stmt *my_ymod; yang_stmt *my_ymod;
clicon_debug(1, "%s %s", __FUNCTION__, body);
my_ymod = ys_module(yp); my_ymod = ys_module(yp);
yspec = ys_spec(yp); yspec = ys_spec(yp);
if (nodeid_split(body, &prefix, &id) < 0) if (nodeid_split(body, &prefix, &id) < 0)
@ -667,7 +672,6 @@ xml2json1_cbuf(cbuf *cb,
modname0 = modname; /* modname0 is ancestor ns passed to child */ modname0 = modname; /* modname0 is ancestor ns passed to child */
} }
childt = child_type(x); childt = child_type(x);
if (pretty==2) if (pretty==2)
cprintf(cb, "#%s_array, %s_child ", cprintf(cb, "#%s_array, %s_child ",
arraytype2str(arraytype), arraytype2str(arraytype),
@ -687,12 +691,18 @@ xml2json1_cbuf(cbuf *cb,
switch (childt){ switch (childt){
case NULL_CHILD: case NULL_CHILD:
/* If x is a container, use {} instead of null /* If x is a container, use {} instead of null
* That is, x is not a list or leaf * if leaf or leaf-list then assume EMPTY type, then [null]
* else null
*/ */
if (ys && yang_keyword_get(ys) == Y_CONTAINER) if (ys && yang_keyword_get(ys) == Y_CONTAINER)
cprintf(cb, "{}"); cprintf(cb, "{}");
else{
if (ys &&
(yang_keyword_get(ys) == Y_LEAF || yang_keyword_get(ys) == Y_LEAF_LIST))
cprintf(cb, "[null]");
else else
cprintf(cb, "null"); cprintf(cb, "null");
}
break; break;
case BODY_CHILD: case BODY_CHILD:
break; break;
@ -756,6 +766,7 @@ xml2json1_cbuf(cbuf *cb,
xc = xml_child_i(x, i); xc = xml_child_i(x, i);
if (xml_type(xc) == CX_ATTR) if (xml_type(xc) == CX_ATTR)
continue; /* XXX Only xmlns attributes mapped */ continue; /* XXX Only xmlns attributes mapped */
xc_arraytype = array_eval(i?xml_child_i(x,i-1):NULL, xc_arraytype = array_eval(i?xml_child_i(x,i-1):NULL,
xc, xc,
xml_child_i(x, i+1)); xml_child_i(x, i+1));

View file

@ -127,7 +127,6 @@ new "waiting"
wait_backend wait_backend
wait_restconf wait_restconf
# First vanilla (protocol) case # First vanilla (protocol) case
new "netconf validate empty" new "netconf validate empty"
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$" expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
@ -171,17 +170,17 @@ new "restconf DELETE whole datastore"
expectfn 'curl -s -X DELETE http://localhost/restconf/data' 0 "" expectfn 'curl -s -X DELETE http://localhost/restconf/data' 0 ""
new "restconf set protocol tcp+udp fail" new "restconf set protocol tcp+udp fail"
expecteq "$(curl -s -X PUT http://localhost/restconf/data/system:system/protocol -d '{"system:protocol":{"tcp": null, "udp": null}}')" 0 '{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"bad-element","error-info":{"bad-element":"udp"},"error-severity":"error","error-message":"Element in choice statement already exists"}}} ' expecteq "$(curl -s -X PUT http://localhost/restconf/data/system:system/protocol -d '{"system:protocol":{"tcp": [null], "udp": [null]}}')" 0 '{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"bad-element","error-info":{"bad-element":"udp"},"error-severity":"error","error-message":"Element in choice statement already exists"}}} '
new "restconf set protocol tcp" new "restconf set protocol tcp"
expecteq "$(curl -s -X PUT http://localhost/restconf/data/system:system/protocol -d {\"system:protocol\":{\"tcp\":null}})" 0 "" expecteq "$(curl -s -X PUT http://localhost/restconf/data/system:system/protocol -d {\"system:protocol\":{\"tcp\":[null]}})" 0 ""
new "restconf get protocol tcp" new "restconf get protocol tcp"
expecteq "$(curl -s -X GET http://localhost/restconf/data/system:system)" 0 '{"system:system":{"protocol":{"tcp":null}}} expecteq "$(curl -s -X GET http://localhost/restconf/data/system:system)" 0 '{"system:system":{"protocol":{"tcp":[null]}}}
' '
new "restconf set protocol tcp+udp fail" new "restconf set protocol tcp+udp fail"
expecteq "$(curl -s -X PUT http://localhost/restconf/data/system:system/protocol -d '{"system:protocol":{"tcp": null, "udp": null}}')" 0 '{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"bad-element","error-info":{"bad-element":"udp"},"error-severity":"error","error-message":"Element in choice statement already exists"}}} ' expecteq "$(curl -s -X PUT http://localhost/restconf/data/system:system/protocol -d '{"system:protocol":{"tcp": [null], "udp": [null]}}')" 0 '{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"bad-element","error-info":{"bad-element":"udp"},"error-severity":"error","error-message":"Element in choice statement already exists"}}} '
new "cli set protocol udp" new "cli set protocol udp"
expectfn "$clixon_cli -1 -f $cfg -l o set system protocol udp" 0 "^$" expectfn "$clixon_cli -1 -f $cfg -l o set system protocol udp" 0 "^$"