* Fixed: [JSON leaf-list output single element leaf-list does not use array](https://github.com/clicon/clixon/issues/261)
This commit is contained in:
parent
9fce0a1214
commit
562320dcbc
3 changed files with 113 additions and 14 deletions
|
|
@ -72,6 +72,7 @@ Users may have to change how they access the system
|
|||
|
||||
### Corrected Bugs
|
||||
|
||||
* Fixed: [JSON leaf-list output single element leaf-list does not use array](https://github.com/clicon/clixon/issues/261)
|
||||
* Fixed: Netconf diff callback did not work with choice and same value replace
|
||||
* Eg if YANG is `choice c { leaf x; leaf y }` and XML changed from `<x>42</x>` to `<y>42</y>` the datastrore changed, but was not detected by diff algorithms and provided to validate callbacks.
|
||||
* Thanks: Alexander Skorichenko, Netgate
|
||||
|
|
|
|||
|
|
@ -36,6 +36,8 @@
|
|||
* JSON syntax is according to:
|
||||
* http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf
|
||||
* RFC 7951 JSON Encoding of Data Modeled with YANG
|
||||
* XXX: The complexity of xml2json1_cbuf() mapping from internal cxobj structure to JSON output
|
||||
* needs a rewrite due to complexity of lists/leaf-lists/null-values, etc.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
|
|
@ -180,14 +182,21 @@ arraytype2str(enum array_element_type lt)
|
|||
}
|
||||
|
||||
/*! Check typeof x in array
|
||||
*
|
||||
* Check if element is in an array, and if so, if it is in the start "[x,", in the middle: "[..,x,..]"
|
||||
* in the end: ",x]", or a single element: "[x]"
|
||||
* Some complexity when x is in different namespaces
|
||||
* @param[in] xprev The previous element (if any)
|
||||
* @param[in] x The element itself
|
||||
* @param[in] xnext The next element (if any)
|
||||
* @retval arraytype Type of array
|
||||
*/
|
||||
static enum array_element_type
|
||||
array_eval(cxobj *xprev,
|
||||
cxobj *x,
|
||||
cxobj *xnext)
|
||||
{
|
||||
enum array_element_type array = NO_ARRAY;
|
||||
enum array_element_type arraytype = NO_ARRAY;
|
||||
int eqprev=0;
|
||||
int eqnext=0;
|
||||
yang_stmt *ys;
|
||||
|
|
@ -196,10 +205,9 @@ array_eval(cxobj *xprev,
|
|||
|
||||
nsx = xml_find_type_value(x, NULL, "xmlns", CX_ATTR);
|
||||
if (xml_type(x) != CX_ELMNT){
|
||||
array=BODY_ARRAY;
|
||||
arraytype = BODY_ARRAY;
|
||||
goto done;
|
||||
}
|
||||
ys = xml_spec(x);
|
||||
if (xnext &&
|
||||
xml_type(xnext)==CX_ELMNT &&
|
||||
strcmp(xml_name(x), xml_name(xnext))==0){
|
||||
|
|
@ -217,17 +225,25 @@ array_eval(cxobj *xprev,
|
|||
eqprev++;
|
||||
}
|
||||
if (eqprev && eqnext)
|
||||
array = MIDDLE_ARRAY;
|
||||
arraytype = MIDDLE_ARRAY;
|
||||
else if (eqprev)
|
||||
array = LAST_ARRAY;
|
||||
arraytype = LAST_ARRAY;
|
||||
else if (eqnext)
|
||||
array = FIRST_ARRAY;
|
||||
else if (ys && yang_keyword_get(ys) == Y_LIST)
|
||||
array = SINGLE_ARRAY;
|
||||
arraytype = FIRST_ARRAY;
|
||||
else if ((ys = xml_spec(x)) != NULL) {
|
||||
if (yang_keyword_get(ys) == Y_LIST
|
||||
#if 0 /* XXX instead see special case in xml2json_encode_leafs */
|
||||
|| yang_keyword_get(ys) == Y_LEAF_LIST
|
||||
#endif
|
||||
)
|
||||
arraytype = SINGLE_ARRAY;
|
||||
else
|
||||
arraytype = NO_ARRAY;
|
||||
}
|
||||
else
|
||||
array = NO_ARRAY;
|
||||
arraytype = NO_ARRAY;
|
||||
done:
|
||||
return array;
|
||||
return arraytype;
|
||||
}
|
||||
|
||||
/*! Escape a json string as well as decode xml cdata
|
||||
|
|
@ -414,7 +430,7 @@ json2xml_decode(cxobj *x,
|
|||
enum rfc_6020 keyword;
|
||||
cxobj *xc;
|
||||
int ret;
|
||||
yang_stmt *ytype;
|
||||
yang_stmt *ytype = NULL;
|
||||
|
||||
if ((y = xml_spec(x)) != NULL){
|
||||
keyword = yang_keyword_get(y);
|
||||
|
|
@ -514,8 +530,9 @@ xml2json_encode_identityref(cxobj *xb,
|
|||
}
|
||||
|
||||
/*! Encode leaf/leaf_list types from XML to JSON
|
||||
* @param[in] x XML body
|
||||
* @param[in] ys Yang spec of parent
|
||||
* @param[in] xb XML body
|
||||
* @param[in] xp XML parent
|
||||
* @param[in] yp Yang spec of parent
|
||||
* @param[out] cb0 Encoded string
|
||||
*/
|
||||
static int
|
||||
|
|
@ -561,8 +578,9 @@ xml2json_encode_leafs(cxobj *xb,
|
|||
if (xml2json_encode_identityref(xb, body, yp, cb) < 0)
|
||||
goto done;
|
||||
}
|
||||
else
|
||||
else{
|
||||
cprintf(cb, "%s", body);
|
||||
}
|
||||
}
|
||||
else
|
||||
cprintf(cb, "%s", body);
|
||||
|
|
@ -577,6 +595,12 @@ xml2json_encode_leafs(cxobj *xb,
|
|||
case CGV_UINT64:
|
||||
case CGV_DEC64:
|
||||
case CGV_BOOL:
|
||||
#if 1 /* Special case */
|
||||
if (yang_keyword_get(yp) == Y_LEAF_LIST
|
||||
&& xml_child_nr_type(xml_parent(xp), CX_ELMNT) == 1)
|
||||
cprintf(cb, "[%s]", body);
|
||||
else
|
||||
#endif
|
||||
cprintf(cb, "%s", body);
|
||||
quote = 0;
|
||||
break;
|
||||
|
|
|
|||
74
test/test_json_list.sh
Executable file
74
test/test_json_list.sh
Executable file
|
|
@ -0,0 +1,74 @@
|
|||
#!/usr/bin/env bash
|
||||
# Test: JSON (leaf-)list and YANG. See RFC7951 sec 5.3 / 5.4
|
||||
|
||||
# Magic line must be first in script (see README.md)
|
||||
s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi
|
||||
|
||||
: ${clixon_util_json:=clixon_util_json}
|
||||
: ${clixon_util_xml:=clixon_util_xml}
|
||||
|
||||
fyang=$dir/json.yang
|
||||
cat <<EOF > $fyang
|
||||
module json{
|
||||
prefix ex;
|
||||
namespace "urn:example:clixon";
|
||||
container c{
|
||||
leaf-list l1{
|
||||
type int32;
|
||||
}
|
||||
list l2{
|
||||
key name;
|
||||
leaf name{
|
||||
type int32;
|
||||
}
|
||||
leaf value{
|
||||
type string;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
# JSON list input/output tests auth test with arguments:
|
||||
# 1. test name
|
||||
# 2. JSON
|
||||
# 3. XML
|
||||
function testrun()
|
||||
{
|
||||
test=$1
|
||||
json=$2
|
||||
xml=$3
|
||||
|
||||
new "$test json in/out"
|
||||
expecteofx "$clixon_util_json -jy $fyang -D $DBG" 0 "$json" "$json"
|
||||
|
||||
new "$test json in / xml out"
|
||||
expecteofx "$clixon_util_json -y $fyang -D $DBG" 0 "$json" "$xml"
|
||||
|
||||
new "$test xml in / json out"
|
||||
expecteofx "$clixon_util_xml -ojvy $fyang -D $DBG" 0 "$xml" "$json"
|
||||
}
|
||||
|
||||
new "test params: -y $fyang"
|
||||
|
||||
testrun "one leaf-list" '{"json:c":{"l1":[1]}}' '<c xmlns="urn:example:clixon"><l1>1</l1></c>'
|
||||
|
||||
testrun "two leaf-list" '{"json:c":{"l1":[1,2]}}' '<c xmlns="urn:example:clixon"><l1>1</l1><l1>2</l1></c>'
|
||||
|
||||
testrun "three leaf-list" '{"json:c":{"l1":[1,2,3]}}' '<c xmlns="urn:example:clixon"><l1>1</l1><l1>2</l1><l1>3</l1></c>'
|
||||
|
||||
testrun "one list" '{"json:c":{"l2":[{"name":1,"value":"x"}]}}' '<c xmlns="urn:example:clixon"><l2><name>1</name><value>x</value></l2></c>'
|
||||
|
||||
testrun "two list" '{"json:c":{"l2":[{"name":1,"value":"x"},{"name":2,"value":"y"}]}}' '<c xmlns="urn:example:clixon"><l2><name>1</name><value>x</value></l2><l2><name>2</name><value>y</value></l2></c>'
|
||||
|
||||
testrun "three list" '{"json:c":{"l2":[{"name":1,"value":"x"},{"name":2,"value":"y"},{"name":3,"value":"z"}]}}' '<c xmlns="urn:example:clixon"><l2><name>1</name><value>x</value></l2><l2><name>2</name><value>y</value></l2><l2><name>3</name><value>z</value></l2></c>'
|
||||
|
||||
rm -rf $dir
|
||||
|
||||
# unset conditional parameters
|
||||
unset clixon_util_json
|
||||
unset clixon_util_xml
|
||||
|
||||
new "endtest"
|
||||
endtest
|
||||
Loading…
Add table
Add a link
Reference in a new issue