Skip to content

JSON parser: error data path loses ancestors and keys when list keys follow other members of a list entry #2586

Description

@pepa-cz

When JSON data contain a list entry whose key members come after other members (valid JSON – object members
are unordered and RFC 7951 does not require keys to be first), errors found in the members parsed before the keys
are reported with a truncated data path. The path misses not only the predicate of the list entry, but also all
its ancestors, so it is not a valid absolute data path at all (e.g. /test:l/e, although l is not a top-level
node).

The same data with the keys placed first produce the correct path (/test:top/l[name='k']/e).

Reproducer

test.yang:

module test {
  yang-version 1.1;
  namespace "urn:test";
  prefix t;

  container top {
    list l {
      key "name";
      leaf name {
        type string;
      }
      leaf e {
        type enumeration {
          enum a;
        }
      }
      container c {
        leaf-list ll {
          type string;
        }
      }
    }
  }
}

Data files and results of yanglint -f json -t config test.yang <file>:

file data reported path
enum-key-first.json {"test:top": {"l": [{"name": "k", "e": "bogus"}]}} /test:top/l[name='k']/e ✔
enum-key-last.json {"test:top": {"l": [{"e": "bogus", "name": "k"}]}} /test:l/e ✘
dup-key-first.json {"test:top": {"l": [{"name": "k", "c": {"ll": ["x", "x"]}}]}} /test:top/l[name='k']/c/ll[.='x'] ✔
dup-key-last.json {"test:top": {"l": [{"c": {"ll": ["x", "x"]}, "name": "k"}]}} /test:l/c/ll[.='x'] ✘

Full output:

$ yanglint -f json -t config test.yang enum-key-first.json
libyang err : Invalid enumeration value "bogus". (/test:top/l[name='k']/e) (line 1)
YANGLINT[E]: Failed to parse input data file "enum-key-first.json".
$ yanglint -f json -t config test.yang enum-key-last.json
libyang err : Invalid enumeration value "bogus". (/test:l/e) (line 1)
YANGLINT[E]: Failed to parse input data file "enum-key-last.json".
$ yanglint -f json -t config test.yang dup-key-first.json
libyang err : Duplicate instance of "ll". (/test:top/l[name='k']/c/ll[.='x']) (line 1)
libyang err : Duplicate instance of "ll". (/test:top/l[name='k']/c/ll[.='x']) (line 1)
YANGLINT[E]: Failed to parse input data file "dup-key-first.json".
$ yanglint -f json -t config test.yang dup-key-last.json
libyang err : Duplicate instance of "ll". (/test:l/c/ll[.='x']) (line 1)
libyang err : Duplicate instance of "ll". (/test:l/c/ll[.='x']) (line 1)
YANGLINT[E]: Failed to parse input data file "dup-key-last.json".

The same data without the error are accepted, i.e. a key placed after other members is valid input
(ok-key-last.json: {"test:top": {"l": [{"c": {"ll": ["x"]}, "name": "k"}]}}):

$ yanglint -f json -t config test.yang ok-key-last.json
{
  "test:top": {
    "l": [
      {
        "name": "k",
        "c": {
          "ll": [
            "x"
          ]
        }
      }
    ]
  }
}

Note that the duplicate leaf-list is reported correctly when it is a direct child of the list entry (it is validated
only after the whole entry, including its keys, is parsed). It is truncated when it is nested deeper (c/ll),
because the nested subtree is validated before the keys of the enclosing list entry are parsed.

Expected behavior

The reported path should be a valid absolute data path. Ideally the full path with the list keys
(/test:top/l[name='k']/e), because the keys are present in the data. If the keys cannot be known at the time the
error is detected, at least the ancestors should be kept (/test:top/l/e), so that the error can be located.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions