javajsonpathjayway

Get Json path of objects when navigation through a Json using Java and Jayway JsonPath


I am witing a user interface in Java that allows the enduser to navigate in a JSON using Jayway JsonPath.

So given the example below

{
    "people": [
        {
            "id": 1,
            "fname": "Henry",
            "lname": "Cavendish",
            "profession": "scientist",
            "research": [
                {
                    "area": "Chemistry",
                    "years": [
                        {
                            "year": 1766
                        },
                        {
                            "year": 1781
                        }
                    ]
                },
                {
                    "area": "Density of the Earth",
                    "years": [
                        {
                            "year": 1797
                        }
                    ]
                },
                {
                    "area": "Electricity",
                    "years": [
                        {
                            "year": 1771
                        },
                        {
                            "year": 1781
                        }
                    ]
                }
            ]
        },
        {
            "id": 1,
            "fname": "Isaac",
            "lname": "Newton",
            "profession": "scientist",
            "research": [
                {
                    "area": "Calculus",
                    "years": [
                        {
                            "year": 1666
                        },
                        {
                            "year": 1669
                        }
                    ]
                },
                {
                    "area": "Optics",
                    "years": [
                        {
                            "year": 1666
                        },
                        {
                            "year": 1675
                        }
                    ]
                },
                {
                    "area": "Gravity",
                    "years": [
                        {
                            "year": 1679
                        },
                        {
                            "year": 1712
                        }
                    ]
                }
            ]
        }
    ]
}

the user can for example use

$.people[*].research[*].years[*].year

to query all years. This is demonstrated with the following Java code

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;

import com.jayway.jsonpath.JsonPath;

public class PathTest {
    public static void main(String[] args) throws IOException {
        byte[] bytes = Files
        .readAllBytes(Paths.get("test.json"));
        String json = new String(bytes, StandardCharsets.UTF_8);
        JsonPath path = JsonPath.compile("$.people[*].research[*].years[*].year");
        List<Integer> yearList = path.read(json);
        for (Integer year : yearList)
            System.out.println(year);
    }
}

which gives

1766
1781
1797
1771
1781
1666
1669
1666
1675
1679
1712

on execution. Now I would like to get the JsonPath of each node in the result like

1766 $.people[0].research[0].years[0].year
1781 $.people[0].research[0].years[1].year
1797 $.people[0].research[1].years[0].year
1771 $.people[0].research[2].years[0].year
1781 $.people[0].research[2].years[1].year
1666 $.people[1].research[0].years[0].year
1669 $.people[1].research[0].years[1].year
1666 $.people[1].research[1].years[0].year
1675 $.people[1].research[1].years[1].year
1679 $.people[1].research[2].years[0].year
1712 $.people[1].research[2].years[1].year

Is there any way to retrieve the path information for each of the nodes returned?

Thanks in advance!


Solution

  • You can use library Josson to do transformation and flatten the JSON.

    https://github.com/octomix/josson

    Deserialization

    Josson josson = Josson.fromJsonString(
        "{" +
        "    \"people\": [" +
        "        {" +
        "            \"id\": 1," +
        "            \"fname\": \"Henry\"," +
        "            \"lname\": \"Cavendish\"," +
        "            \"profession\": \"scientist\"," +
        "            \"research\": [" +
        "                {" +
        "                    \"area\": \"Chemistry\"," +
        "                    \"years\": [" +
        "                        {" +
        "                            \"year\": 1766" +
        "                        }," +
        "                        {" +
        "                            \"year\": 1781" +
        "                        }" +
        "                    ]" +
        "                }," +
        "                {" +
        "                    \"area\": \"Density of the Earth\"," +
        "                    \"years\": [" +
        "                        {" +
        "                            \"year\": 1797" +
        "                        }" +
        "                    ]" +
        "                }," +
        "                {" +
        "                    \"area\": \"Electricity\"," +
        "                    \"years\": [" +
        "                        {" +
        "                            \"year\": 1771" +
        "                        }," +
        "                        {" +
        "                            \"year\": 1781" +
        "                        }" +
        "                    ]" +
        "                }" +
        "            ]" +
        "        }," +
        "        {" +
        "            \"id\": 1," +
        "            \"fname\": \"Isaac\"," +
        "            \"lname\": \"Newton\"," +
        "            \"profession\": \"scientist\"," +
        "            \"research\": [" +
        "                {" +
        "                    \"area\": \"Calculus\"," +
        "                    \"years\": [" +
        "                        {" +
        "                            \"year\": 1666" +
        "                        }," +
        "                        {" +
        "                            \"year\": 1669" +
        "                        }" +
        "                    ]" +
        "                }," +
        "                {" +
        "                    \"area\": \"Optics\"," +
        "                    \"years\": [" +
        "                        {" +
        "                            \"year\": 1666" +
        "                        }," +
        "                        {" +
        "                            \"year\": 1675" +
        "                        }" +
        "                    ]" +
        "                }," +
        "                {" +
        "                    \"area\": \"Gravity\"," +
        "                    \"years\": [" +
        "                        {" +
        "                            \"year\": 1679" +
        "                        }," +
        "                        {" +
        "                            \"year\": 1712" +
        "                        }" +
        "                    ]" +
        "                }" +
        "            ]" +
        "        }" +
        "    ]" +
        "}");
    

    Transformation

    JsonNode node = josson.getNode(
        "map(people.map(research.map(years.map(year)))).flatten('.','[%d]')");
    System.out.println(node.toPrettyString());
    System.out.println("------");
    node.fields().forEachRemaining(entry ->
        System.out.println("$." + entry.getKey() + " = " + entry.getValue().asText()));
    

    Output

    {
      "people[0].research[0].years[0].year" : 1766,
      "people[0].research[0].years[1].year" : 1781,
      "people[0].research[1].years[0].year" : 1797,
      "people[0].research[2].years[0].year" : 1771,
      "people[0].research[2].years[1].year" : 1781,
      "people[1].research[0].years[0].year" : 1666,
      "people[1].research[0].years[1].year" : 1669,
      "people[1].research[1].years[0].year" : 1666,
      "people[1].research[1].years[1].year" : 1675,
      "people[1].research[2].years[0].year" : 1679,
      "people[1].research[2].years[1].year" : 1712
    }
    ------
    $.people[0].research[0].years[0].year = 1766
    $.people[0].research[0].years[1].year = 1781
    $.people[0].research[1].years[0].year = 1797
    $.people[0].research[2].years[0].year = 1771
    $.people[0].research[2].years[1].year = 1781
    $.people[1].research[0].years[0].year = 1666
    $.people[1].research[0].years[1].year = 1669
    $.people[1].research[1].years[0].year = 1666
    $.people[1].research[1].years[1].year = 1675
    $.people[1].research[2].years[0].year = 1679
    $.people[1].research[2].years[1].year = 1712