PathNotFoundException: Missing property in path while iterating over recursive JSON structure

2.4k Views Asked by At

I have a JSON structure where some objects can have arbitrary names and i want to normalize this structure, such that the objects become anonymous, but can be identified by a "name" property.
From

{
    {
        "arbitrary_name": {
            ...
    }
}

to

{
    "name": "arbitrary_name",
    ...
}

For the first step, i want to add a name property to the "arbitrary-name" object and in the next step remove the "arbitrary-name" object and move it's properties one level up.

First, i'm querying the JSON structure (using https://github.com/json-path/JsonPath) for all paths pointing to objects, which need to be normalized. They are all positioned under an array with name "children". Then i'm iterating this paths, get the objects' values and add a name property.
My approach works fine on the top-level object, but if they are nested (child objects -> service.children[0].arbitrary_name1.children[0]), JsonPath throws an exception and i don't get it what property is missing. I printed all possible paths in this structure and the queried path (which causes the exception) is printed too.
My input looks like this:

{
    "service": {
        "foo": "bar",
        "children": [
            {
                "arbitrary_name1": {
                    "foo": "bar",
                    "children": [
                        {
                            "arbitrary_name_2": {
                                "foo": "bar"
                            }
                        }
                    ]
                }
            }
        ]
    }
}

My code:

    final File src = Files.readString(xxx); // Path to file with JSON content
    final Configuration c = Configuration.defaultConfiguration().setOptions(Option.ALWAYS_RETURN_LIST, Option.AS_PATH_LIST);
    final DocumentContext pathsContext = JsonPath.parse(src, c);
    final DocumentContext valuesContext = JsonPath.parse(src);
    final Collection<String> pathsToObjects = pathsContext.read("$..children[*]");
    /* prints:
        $['service']['children'][0]
        $['service']['children'][0]['arbitrary_name1']['children'][0]
    */
    for (String jsonPath : pathsToObjects) {
        Map<String, Map> valuesOfOuterObject = valuesContext.read(jsonPath);    // Exception on 2nd path
        String name = valuesOfOuterObject.keySet().stream().findFirst().get();
        final Map<String, Object> valuesOfInnerObject = valuesOfOuterObject.get(name);
        valuesOfInnerObject.put("name", name);
        valuesContext.set(jsonPath, valuesOfInnerObject);
    }

The corresponding exception says:

com.jayway.jsonpath.PathNotFoundException: Missing property in path $['service']['children'][0]['arbitrary_name1']

What am i missing or is there an easier approach?

0

There are 0 best solutions below