1

For example I have Json like this

{
name: Alex,
lastName: Smith,
delivery: {
   street: 7599 King George Blvd,
   name : PIETER CIERE
},
paymentAddressData: [
    {
    email: [email protected],
    name: Bobby,
    phone2: 123456
     },
    {
    email: [email protected],
    name: Bobby,
    phone2: 123456
     }
]

}

And I need to change value in "name" field, only in root node and in "paymentAddressData" arrayNode in all entries. IN all other places, value must be as it is. How I can implement it using Jackson or other tools ? Would be grateful for any advice!

1
  • This is invalid JSON code. You need to put all strings in quotes "". Commented Apr 16, 2022 at 10:14

2 Answers 2

2

I implemented my own dynamic method for our Test automation (via REST Assured) where you fill a HashMap with KeyPath conventions (see below) for modifying any several keys at once and finally return the according new Json-String for both JSONObject and JSONArray (beginning and ending with only one "[" and "]"). I never needed to use modify JSONArrays with starting multiple square brackets which shouldn't be used mostly in common.

Just extract your origin JSON as String modifying it and then write back to your according file/path.

Here is an JSON example:

{
    "personalDetails": [
        {
            "name": "John",
            "city": "Berlin",
            "job": "Teacher",
            "age": 42,
            "children": [
                {
                    "name": "Kevin",
                    "city": "Berlin",
                    "age": 14
                },
                {
                    "name": "Lisa",
                    "city": "Berlin",
                    "age": 8
                }
            ]
        },
        {
            "name": "Mark",
            "city": "Oslo",
            "job": "Doctor",
            "children": []
        }
    ]
}

For example, you want to modify following keys:

  • Age (Lisa) -> From: 8 , To: 9 , KeyPath: "personalDetails[0].children[1].age"

  • Job (Mark) -> From: "Doctor" , To: "Chiropractor" , KeyPath: "personalDetails[1].job"

Use your given Json-String and following HashMap for filling the arguments in my dynamic method below according to my examples:

HashMap<String, Object> modifyMap = new HashMap<String, Object>() {{
            put("personalDetails[0].children[1].age", 9);
            put("personalDetails[1].job", "Chiropractor");
        }};

Call this method with the extracted, modifed Json-String

// Modify any given JsonObject or JsonArray due to KeyPath conventions
protected static String modifiedJson(String oldJson, Map<String, Object> modifyMap) {

    JSONObject defaultJson = new JSONObject("{}");
    Object newJson = defaultJson;

    Pattern pattern = Pattern.compile("\\[(\\d+)]");

    for (String keyPath : modifyMap.keySet()) {

        String[] keyPathTrimmings = keyPath.split("\\.");
        int sizeOfTrimmings = keyPathTrimmings.length;

        JSONObject[] jsonObjects = new JSONObject[sizeOfTrimmings];
        Matcher matcher = pattern.matcher(keyPathTrimmings[sizeOfTrimmings - 1]);
        newJson = matcher.find(0) ?
                newJson.equals(defaultJson) ? new JSONArray(oldJson) : newJson :
                newJson.equals(defaultJson) ? new JSONObject(oldJson) : newJson;
        jsonObjects[0] = matcher.find(0) ?
                newJson instanceof JSONArray ? ((JSONArray) newJson).getJSONObject(Integer.parseInt(matcher.group(1))) : defaultJson :
                newJson instanceof JSONObject ? (JSONObject) newJson : defaultJson;

        for (int pos = 0; pos < sizeOfTrimmings; pos++) {

            String actualKey = keyPathTrimmings[pos].replaceAll("\\[(\\d+)]", "");

            if (pos == sizeOfTrimmings - 1) {
                jsonObjects[pos].put(actualKey, modifyMap.get(keyPath));
            } else {
                matcher = pattern.matcher(keyPathTrimmings[pos]);
                jsonObjects[pos + 1] = matcher.find(0) ?
                        jsonObjects[pos].getJSONArray(actualKey).getJSONObject(Integer.parseInt(matcher.group(1))) :
                        jsonObjects[pos].getJSONObject(actualKey);
            }
        }
    }
    return newJson.toString();
}
Sign up to request clarification or add additional context in comments.

Comments

2

Instead of using Jackson I would prefer the JsonPath library, because it offers a more powerful API for accessing and modifying JSON content in a path-based manner. For some examples I recommend reading the article Baeldung - Introduction to JsonPath.

Using methods JsonPath.parse and WriteContext.set you can do it with a few lines. The following code will replace the name in the root node by "Alice" and the name in all paymentAddressData nodes by "Charlie".

File file = new File("example.json");
String json = JsonPath.parse(file)
        .set("$.name", "Alice")
        .set("$.paymentAddressData[*].name", "Charlie")
        .jsonString();
System.out.println(json);

If you want another value for replacing the JSON names, then you will need to adapt the .set(...) calls in the code above according to your needs. For more complex logics you might want to use .map(...) instead of .set(...).

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.