3

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.

Pramod S. Nikam
  • 4,271
  • 4
  • 38
  • 62
  • Do you **have** to use that direct access? Couldn't you simply iterate over the differents results and children and accumulate them together in a array – Lino Apr 14 '20 at 09:01
  • 1
    @Lino - Yes I dont want to iterate because I am looking for dynamic and and my node length id going to be changing – Pramod S. Nikam Apr 14 '20 at 09:02
  • Looking for direct access. – Pramod S. Nikam Apr 14 '20 at 09:04
  • 5
    What you're looking for is called [JSONPath](https://restfulapi.net/json-jsonpath/), which plays the same role for JSON that [XPath](https://www.w3.org/TR/1999/REC-xpath-19991116/) does for XML. --- See [Jayway JsonPath](https://github.com/json-path/JsonPath#jayway-jsonpath) for Java library. – Andreas Apr 14 '20 at 09:05
  • @Andreas - Thanks, Yeah something like that, looks like jsonpath implementation is available for java at https://github.com/json-path/JsonPath – Pramod S. Nikam Apr 14 '20 at 09:08
  • 2
    @PramodS.Nikam I already posted that link: `Jayway JsonPath` → `https://github.com/json-path/JsonPath#jayway-jsonpath` – Andreas Apr 14 '20 at 09:26
  • Take a look on similar question where `JsonPath` was used: [How to modify the value of a JsonNode recursively using Jackson](https://stackoverflow.com/questions/55560223/how-to-modify-the-value-of-a-jsonnode-recursively-using-jackson), [How to get in Java all output paths ...](https://stackoverflow.com/questions/55423089/how-to-get-in-java-all-output-paths-of-a-jsonpath-in-order-to-replace-existing-v) – Michał Ziober Apr 14 '20 at 22:44

2 Answers2

0

If you may switch to Gson library you may use im.wilk.vor:Voritem library gitHub or in Maven repository.

VorItem vorItemFactory = VorItemFactoryBuilder.standard.build();
JsonElement je = JsonParser.parse(...)

VorItem vi = vorItemFactory.from(je);
VorItem result = vorItemFactory.empty();

for (int idx = 0; idx < vi.get("result").list().size(); idx++) {
    result.get(idx).set("name", vi.get("result").get(idx).get("associations/child/name");
    result.get(idx).set("key", vi.get("result").get(idx).get("associations/child/key");

}

return result.asJsonElement().toString();
0

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");
Pramod S. Nikam
  • 4,271
  • 4
  • 38
  • 62