diff --git a/CHANGELOG.md b/CHANGELOG.md index 06601867..6dddc838 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,8 +27,10 @@ * JSON changes * Non-pretty-print output removed all extra spaces. * Example: `{"nacm-example:x": 42}` --> {"nacm-example:x":42}` - * Empty JSON container changed from `null` to `{}`. - * Empty list and leafs remain as `null` + * Empty JSON values changed from `null` to: + * Empty yang container encoded as `{}` + * Empty leaf/leaf-list of type empty encoded as `[null]` + * Other empty values remain as `null` ### Minor changes * Removed unnecessary configure dependencies diff --git a/apps/restconf/restconf_methods_get.c b/apps/restconf/restconf_methods_get.c index 1fb8ad10..60038c1a 100644 --- a/apps/restconf/restconf_methods_get.c +++ b/apps/restconf/restconf_methods_get.c @@ -187,18 +187,17 @@ api_data_get2(clicon_handle h, } else{ #if 0 - if (debug){ - cbuf *ccc=cbuf_new(); - if (clicon_xml2cbuf(ccc, xret, 0, 0) < 0) - goto done; - clicon_debug(1, "%s xret: %s", - __FUNCTION__, cbuf_get(ccc)); - cbuf_free(ccc); + if (debug){ + cbuf *ccc=cbuf_new(); + if (clicon_xml2cbuf(ccc, xret, 0, 0) < 0) + goto done; + clicon_debug(1, "%s xret: %s", + __FUNCTION__, cbuf_get(ccc)); + cbuf_free(ccc); } #endif - - if (xml2json_cbuf(cbx, xret, pretty) < 0) - goto done; + if (xml2json_cbuf(cbx, xret, pretty) < 0) + goto done; } } else{ diff --git a/lib/src/clixon_json.c b/lib/src/clixon_json.c index 23c9389b..a89a4162 100644 --- a/lib/src/clixon_json.c +++ b/lib/src/clixon_json.c @@ -193,14 +193,14 @@ array_eval(cxobj *xprev, char *ns2; 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; goto done; } ys = xml_spec(x); if (xnext && 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); if ((!nsx && !ns2) || (nsx && ns2 && strcmp(nsx,ns2)==0)) @@ -420,13 +420,17 @@ json2xml_decode(cxobj *x, if (keyword == Y_LEAF || keyword == Y_LEAF_LIST){ if (yang_type_get(y, NULL, &ytype, NULL, NULL, NULL, NULL, NULL) < 0) goto done; - if (ytype) + + if (ytype){ if (strcmp(yang_argument_get(ytype),"identityref")==0){ if ((ret = json2xml_decode_identityref(x, y, xerr)) < 0) goto done; if (ret == 0) goto fail; } + else if (strcmp(yang_argument_get(ytype), "empty")==0) + ; /* dont need to do anything */ + } } } xc = NULL; @@ -464,6 +468,7 @@ xml2json_encode_identityref(cxobj *xb, yang_stmt *yspec; yang_stmt *my_ymod; + clicon_debug(1, "%s %s", __FUNCTION__, body); my_ymod = ys_module(yp); yspec = ys_spec(yp); if (nodeid_split(body, &prefix, &id) < 0) @@ -667,7 +672,6 @@ xml2json1_cbuf(cbuf *cb, modname0 = modname; /* modname0 is ancestor ns passed to child */ } childt = child_type(x); - if (pretty==2) cprintf(cb, "#%s_array, %s_child ", arraytype2str(arraytype), @@ -687,12 +691,18 @@ xml2json1_cbuf(cbuf *cb, switch (childt){ case NULL_CHILD: /* 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) cprintf(cb, "{}"); - else - cprintf(cb, "null"); + else{ + if (ys && + (yang_keyword_get(ys) == Y_LEAF || yang_keyword_get(ys) == Y_LEAF_LIST)) + cprintf(cb, "[null]"); + else + cprintf(cb, "null"); + } break; case BODY_CHILD: break; @@ -756,6 +766,7 @@ xml2json1_cbuf(cbuf *cb, xc = xml_child_i(x, i); if (xml_type(xc) == CX_ATTR) continue; /* XXX Only xmlns attributes mapped */ + xc_arraytype = array_eval(i?xml_child_i(x,i-1):NULL, xc, xml_child_i(x, i+1)); diff --git a/test/test_choice.sh b/test/test_choice.sh index 5b0d9479..5ead0d93 100755 --- a/test/test_choice.sh +++ b/test/test_choice.sh @@ -127,7 +127,6 @@ new "waiting" wait_backend wait_restconf - # First vanilla (protocol) case new "netconf validate empty" expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$" @@ -171,17 +170,17 @@ new "restconf DELETE whole datastore" expectfn 'curl -s -X DELETE http://localhost/restconf/data' 0 "" 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" -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" -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" -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" expectfn "$clixon_cli -1 -f $cfg -l o set system protocol udp" 0 "^$"