Search code examples
javajsonspringjacksonmodelmapper

How to deep select Nodes based on given depth in Java?


I have json representation like below:

{
  "total": "555",
  "offset": "555",
  "hasMore": "false",
  "results": [
    {
      "associations": {
        "workflowIds": [],
        "companyIds": [],
        "ownerIds": [],
        "child": {
         "name" : "association1",
          "key" : "a1"
        }, 
        "quoteIds": [],
        "contentIds": [],
        "dealIds": [],
        "contactIds": [
          4646915
        ],
        "ticketIds": []
      },
      "scheduledTasks": [
        {
          "taskType": "REMINDER",
          "portalId": 214129,
          "engagementType": "TASK",
          "engagementId": 6604524566,     
          "timestamp": 1586815200000
        }
      ]
    },
    {
      "associations": {
        "workflowIds": [],
        "companyIds": [],
        "ownerIds": [],
        "quoteIds": [],
        "contentIds": [],
        "child": {
         "name" : "association2",
          "key" : "a2"
        }, 
        "dealIds": [],
        "contactIds": [
          4646915
        ],
        "ticketIds": []
      }
    },
    {
      "associations": {
        "workflowIds": [],
        "companyIds": [],
        "ownerIds": [],
        "quoteIds": [],
        "contentIds": [],
        "dealIds": [],
        "child": {
         "name" : "association3",
          "key" : "a3"
        }, 
        "contactIds": [
          3995065
        ],
        "ticketIds": []
      }
    },
    {
      "associations": {
        "workflowIds": [],
        "companyIds": [],
        "ownerIds": [],
        "quoteIds": [],
        "contentIds": [],
        "dealIds": [],
        "contactIds": [
          4648365
        ],
        "ticketIds": []
      }
    }
]
}

I would like to get filtered information (something like sql) of given node by passing node selector string , to achieve this I am doing like below:

ObjectMapper objectMapper = new ObjectMapper();
        JsonNode root = objectMapper.readTree(new File("/Users/pra/automation/foo.json"));
       String result = root.at("/results/0/associations/0/child").toString();
       Assert.assertNotNull(result);

and this code is working as well, it filters first nodes out of array because 0 level index is passed, but I need output for all matching elements, so as to achieve that I passed * instead of 0 but it is not working.

means i am trying something like below ( which is failing ):

String result = root.at("/results/*/associations/*/child").toString();

Desired Output that needed:

[
{
   "name" : "association1",
   "key" : "a1"
},
{
   "name" : "association2",
   "key" : "a2"
},
{
   "name" : "association3",
   "key" : "a3"
}
]

I am open for other java based alternatives to achieve this. Thanks.


Solution

  • I found Andreas suggestion to be very effective and usage friendly, I was able to achieve desired output by using JSONPath library .

    Usage code is as follows:

    ObjectMapper objectMapper = new ObjectMapper();
    String root = objectMapper.readTree(new File("/Users/pramo/automation/foo.json")).toString();
    List<Object> associations = JsonPath.read(root, "$.results[*].associations.child");