0

Hey all I am trying to figure out how to go about updating a part of my json. So far I have not found anywhere that shows me how to do this.

For an example, this is what I am needing to update:

{
    "lastUpdated": "",
    "firetvs": [
        {
            "name": "lr",
            "ip": "",
            "mac": "",
            "token": ""
        },
        {
            "name": "mbr",
            "ip": "",
            "mac": "",
            "token": ""
        },...ETC....

So I am needing to update the data under the

"name": "mbr"
 "mac": ""

part which I would need to update the mac address to something like:

"name": "mbr"
 "mac": "C1:41:Q4:E8:S1:98:V1"

I have found code that allows me to update a standard value like my lastUpdated but not for something that's part of an array:

String jsonObject = "{" + 
    "\"lastUpdated\": \"\"," +
    "\"firetvs\": [" +
        "{" +
            "\"name\": \"lr\"," +
            "\"ip\": \"\"," +
            "\"mac\": \"\"," +
            "\"token\": \"\"" +
        "}," +
        "{" +
            "\"name\": \"mbr\"," +
            "\"ip\": \"\"," +
            "\"mac\": \"\"," +
            "\"token\": \"\"" +
        "}" +
    "]" +
"}";

ObjectMapper objectMapper = new ObjectMapper();
ObjectNode objectNode = null;

try {
    objectNode = objectMapper.readValue(jsonObject, ObjectNode.class);
    objectNode.put("lastUpdated", "02-08-2024");
    Log.d("test", objectNode.toPrettyString());
} catch (JsonProcessingException e) {
    throw new RuntimeException(e);
}

I did find this:

objectNode.with("firetvs").put("mac", "C1:41:Q4:E8:S1:98:V1");

But that wont work since its just going to find the first instance of "mac" and update that value instead of updating the 2nd instance of it. And I also get an error of:

Property 'firetvs' has value that is not of type ObjectNode (but com.fasterxml.jackson.databind.node.ArrayNode)

So, how would I accomplish this?

3
  • I think this might work for you: 1. use objectNode.get("firetvs") method and cast it to and ArrayNode object. 2. Take take ArrayNode object's second element and cast it back to ObjectNode. 3. You can use the put("mac", "C1:41:Q4:E8:S1:98:V1") method now on the object created in the second point. Commented Mar 27, 2024 at 15:00
  • Do you need to put the same mac address to all the elements of the firetvs array or just to specific ones? Commented Mar 27, 2024 at 16:02
  • @dani-vta it would be one specific. I have more to the array but shortened it to 2 so that it would not take up so much space in my question Commented Mar 27, 2024 at 16:36

2 Answers 2

1

You may try JSON library Josson.

https://github.com/octomix/josson

Josson josson = Josson.fromJsonString(
    "{" +
        "\"lastUpdated\": \"\"," +
        "\"firetvs\": [" +
            "{" +
                "\"name\": \"lr\"," +
                "\"ip\": \"\"," +
                "\"mac\": \"\"," +
                "\"token\": \"\"" +
            "}," +
            "{" +
                "\"name\": \"mbr\"," +
                "\"ip\": \"\"," +
                "\"mac\": \"\"," +
                "\"token\": \"\"" +
            "}" +
        "]" +
    "}");
Map<String, JsonNode> params = Map.of(
    "$date", TextNode.valueOf("02-08-2024"),
    "$key", TextNode.valueOf("mbr"),
    "$val", TextNode.valueOf("C1:41:Q4:E8:S1:98:V1")
);
JsonNode node = josson.getNode("field(lastUpdated:$date, firetvs.field(mac:if([name=$key],$val,mac)))", params);
System.out.println(node.toPrettyString());

Output

{
  "lastUpdated" : "02-08-2024",
  "firetvs" : [ {
    "name" : "lr",
    "ip" : "",
    "mac" : "",
    "token" : ""
  }, {
    "name" : "mbr",
    "ip" : "",
    "mac" : "C1:41:Q4:E8:S1:98:V1",
    "token" : ""
  } ]
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the example and link Raymond!
1

If you need to update the mac address of the firetvs elements only under certain conditions, for example that name is equals to mbr, I'm providing an alternative solution with streams.

Basically, the firetvs's elements are streamed via an Iterable, then filtered by keeping only the ones with mbr as their name, and finally updated with the correct mac address.

In the following sample, I've added only a couple of elements within firetvs to not clutter the code. However, here at oneCompiler I've included more elements showing the desired output.

public class Main {
    public static void main(String[] args) throws JsonProcessingException {
        String json = "{\n" +
                "    \"lastUpdated\": \"\",\n" +
                "    \"firetvs\": [\n" +
                "        {\n" +
                "            \"name\": \"lr\",\n" +
                "            \"ip\": \"\",\n" +
                "            \"mac\": \"\",\n" +
                "            \"token\": \"\"\n" +
                "        },\n" +
                "        {\n" +
                "            \"name\": \"mbr\",\n" +
                "            \"ip\": \"\",\n" +
                "            \"mac\": \"\",\n" +
                "            \"token\": \"\"\n" +
                "        }\n" +
                "    ]\n" +
                "}";

        String mac = "C1:41:Q4:E8:S1:98:V1";

        ObjectMapper objectMapper = new ObjectMapper();
        ObjectNode rootNode = objectMapper.readValue(json, ObjectNode.class);
        ArrayNode firetvsNode = (ArrayNode) rootNode.get("firetvs");

        //Creating an Iterable form the Iterator of the firetvs' nodes
        Iterable<JsonNode> iterable = () -> firetvsNode.iterator();

        StreamSupport.stream(iterable.spliterator(), false)     //Streaming the firetvs' nodes
                .filter(node -> node.get("name").asText().equals("mbr"))    //Keeping only the elements with mbr as their name
                .forEach(node -> ((ObjectNode) node).put("mac", mac));  //Updating the mac address of each element

        String jsonMacReplaced = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(rootNode);
        System.out.println(jsonMacReplaced);
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.