Как изменить вложенные элементы Json на Java?
У меня есть Json строка
String jsonStr = "{\"id\": \"11111111\",\"amount\": 10000,\"operation\": {\"id\": \"222222222\"," +
"\"status\": \"SUCCESS\", \"access\": {\"user\": \"Alexa\",\"password\":\"33333333\" }}}";
Мне нужно изменить все элементы id на другое значение. Я попробовал вот так и сяк, но не получается:
JSONObject jsonObject = new JSONObject(jsonStr);
jsonObject.remove("id");
jsonObject.put("id", "000000");
Результат:
{"amount":10000,"operation":{"id":"222222222","status":"SUCCESS","access":{"user":"Alexa","password":"33333333"}},"id":"000000"}
В результате изменяется только первый элемент id, и то оно записывается в конец строки. Как сделать так, чтобы можно было поменять все элементы id?
Ответы (1 шт):
Используя библиотеку FasterXML Jackson, можно прочитать заданную JSON-строку в ObjectNode так как он позволяет менять значения при помощи методов put, set, replace и др., при этом может создаваться новое поле, если не будет найдено существующее
ObjectMapper mapper = new ObjectMapper();
ObjectNode root = (ObjectNode) mapper.readTree(jsonStr);
root.put("id", 324);
root.set("id2", new TextNode("456"));
System.out.println("id:" + root.get("id"));
System.out.println("id2:" + root.get("id2"));
root.put("id", 324);
System.out.println("id:" + root.get("id"));
((ObjectNode) root.get("operation")).put("id", "abcd-ef01-23456789");
System.out.println("op.id:" + root.get("operation").get("id"));
Вывод:
id:324 // заменили на int
id2:"456" // создали новое поле
op.id:"abcd-ef01-23456789" // заменили на другое строковое значение
Также можно реализовать рекурсивную функцию для поиска всех полей и присваивания им нового значения:
static void updateField(ObjectNode node, String fieldName, String newValue) {
if (node.has(fieldName)) // проверить наличие поля в текущем объекте
node.put(fieldName, newValue);
// проверить вложенные поля
for (Iterator<Map.Entry<String, JsonNode>> it = node.fields(); it.hasNext(); ) {
Map.Entry<String, JsonNode> nested = it.next();
if (nested.getValue().isObject()) {
updateField((ObjectNode) nested.getValue(), fieldName, newValue);
}
}
}
// вызов:
updateField(root, "id", "333");
System.out.println("id:" + root.get("id"));
System.out.println("op.id:" + root.get("operation").get("id"));
Вывод:
id:"333"
op.id:"333"
Альтернативный "читерский" вариант -- использовать регулярные выражения и заменять пары "поле": "значение" по совпадению шаблона безо всякого разбора JSON при помощи методов String::replaceAll / String::replaceFirst
System.out.println(jsonStr.replaceAll("(\"id\"\\s*:\\s*)\"([^\"]*)\"", "$1\"5555\""));
System.out.println(jsonStr.replaceFirst("(\"id\"\\s*:\\s*)\"([^\"]*)\"", "$1\"XYZ\""));
Результат:
{"id": "5555","amount": 10000,"operation": {"id": "5555","status": "SUCCESS", "access": {"user": "Alexa","password":"33333333" }}}
{"id": "XYZ","amount": 10000,"operation": {"id": "222222222","status": "SUCCESS", "access": {"user": "Alexa","password":"33333333" }}}