Search code examples
javajsonjackson-databindfasterxmljsonnode

JsonNode - How to update nested values in array


Apologies, Google tells me there are many similar questions to this already asked on Stack Overflow but I'm struggling to find an answer that works for my situation.

I have a Java application that is using JsonNode for the first time (previously mapped to Java classes but that isn't an option on this occasion).

We retrieve a JSON object from a third party, example JSON below:.

[
  {
    "id": "123",
    "name": "name",
    "dateCreated": "2023-08-03T09:38:21.221Z",
    "queues": {
      "wait": [
        {
          "criteria": [
            {
              "type": "s",
              "threshold": 20
            }
          ],
          "groups": [
            {
              "id": "123",
              "name": "Group 1"
            }
          ]
        },
        {
          "criteria": [
            {
              "type": "s",
              "threshold": 10
            }
          ]
        },
        {
          "criteria": [
            {
              "type": "s",
              "threshold": 30
            }
          ]
        },
        {
          "criteria": [
            {
              "type": "s",
              "threshold": 2
            }
          ]
        }
      ]
    }
  }
]

I need to update each 'threshold' value in the wait array and then return the JsonNode to another service.

It's very important I maintain the order of each index in the 'wait' array. Also I can only guarantee that 'threshold' will be within a nested 'criteria' array, I cannot guarantee other values won't be present e.g. the 'groups' array in the example above, but it is important that all fields are maintained and none lost.

I have found out online that JsonNode is immutable and you need to cast to ObjectArray to get the put/set methods, however I can't see how these method work for nested values e.g. I can use it to update 'name' but I am struggling to use it to update anything inside 'queues'.

I have seen some posts regarding ArrayNode but all examples I find regards to replacing an entire array and I only want to update single values inside the array.

Any help is much appreciated.


Solution

  • ObjectNode contains put() method, which can change the value of the node. You have to cast the JsonNode into ObjectNode.

    I could accomplish this using the following code. I am assuming that all the threshold values will be set to a fixed value. In my case I'm assuming it is 50:

               for (JsonNode node : jsonNode) {
                    JsonNode waitNode = node.path("queues").path("wait");
                    if (waitNode.isArray()) {
                        for (JsonNode item : waitNode) {
                            ((ObjectNode) item.path("criteria").get(0)).put("threshold", 50);
                        }
                    }
                }
    
                // Print updated JSON node using jsonNode.toPrettyString()
                System.out.println("JSON after Node edit: " + jsonNode.toPrettyString());