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();
}
"".