Как изменить JsonNode в Java?

109

Мне нужно изменить значение атрибута JSON в Java, я могу получить значение правильно, но не могу изменить JSON.

вот код ниже

  JsonNode blablas = mapper.readTree(parser).get("blablas");
    for (JsonNode jsonNode : blablas) {
        String elementId = jsonNode.get("element").asText();
        String value = jsonNode.get("value").asText();
        if (StringUtils.equalsIgnoreCase(elementId, "blabla")) {
            if(value != null && value.equals("YES")){
                 // I need to change the node to NO then save it into the JSON
            }
        }
    }

Как лучше всего это сделать?

mstfdz
источник
1
Вы можете преобразовать JsonNode в Java Map, например, resultMap = mapper.convertValue(aJsonNode, Map.class);изменить его в Map, а затем снова изменить эту карту на JsonNode. Просто говорю.
MikeJRamsey56

Ответы:

198

JsonNodeнеизменяема и предназначена для синтаксического анализа. Однако его можно преобразовать в ObjectNodeArrayNode), разрешающие мутации:

((ObjectNode)jsonNode).put("value", "NO");

Для массива вы можете использовать:

((ObjectNode)jsonNode).putArray("arrayName").add(object.ge‌​tValue());
Шэрон Бен Ашер
источник
4
пробовал для числового типа, в котором мне нужно изменить значение. У меня есть это исключение:Exception in thread "main" java.lang.ClassCastException: com.fasterxml.jackson.databind.node.IntNode cannot be cast to com.fasterxml.jackson.databind.node.ObjectNode
balboa_21
Вам нужно попробовать «IntNode»
муля 09
6

Добавление ответа, поскольку некоторые другие поддержали комментарии к принятому ответу, они получают это исключение при попытке привести к ObjectNode (включая меня):

Exception in thread "main" java.lang.ClassCastException: 
com.fasterxml.jackson.databind.node.TextNode cannot be cast to com.fasterxml.jackson.databind.node.ObjectNode

Решение состоит в том, чтобы получить «родительский» узел и выполнить put, эффективно заменяя весь узел, независимо от исходного типа узла.

Если вам нужно «изменить» узел, используя существующее значение узла:

  1. get значение / массив JsonNode
  2. Выполните вашу модификацию этого значения / массива
  3. Приступайте к вызову putродителя.

Код, цель которого - изменить subfield, который является дочерним узлом NodeAиNode1 :

JsonNode nodeParent = someNode.get("NodeA")
                .get("Node1");

// Manually modify value of 'subfield', can only be done using the parent.
((ObjectNode) nodeParent).put('subfield', "my-new-value-here");

Кредиты:

Отсюда я черпал вдохновение благодаря wassgreen @

матрица аномалия
источник
5

Ответ @ Sharon-Ben-Asher в порядке.

Но в моем случае для массива я должен использовать:

((ArrayNode) jsonNode).add("value");
Алехандро
источник
4

Я думаю, вы можете просто указать ObjectNode и использовать putметод. Как это

ObjectNode o = (ObjectNode) jsonNode; o.put("value", "NO");

Xdsasdf
источник
2

Вам нужно получить ObjectNodeобъект типа, чтобы устанавливать значения. Взгляните на это

Евгений Халька
источник
0

Просто ради понимания других, которые могут не получить полную картину, следующий код работает для меня, чтобы найти поле, а затем обновить его

ObjectMapper mapper = new ObjectMapper();
JsonNode rootNode = mapper.readTree(JsonString);    
JsonPointer valueNodePointer = JsonPointer.compile("/GrandObj/Obj/field");
JsonPointer containerPointer = valueNodePointer.head();
JsonNode parentJsonNode = rootNode.at(containerPointer);

if (!parentJsonNode.isMissingNode() && parentJsonNode.isObject()) {
    ObjectNode parentObjectNode = (ObjectNode) parentJsonNode;
    //following will give you just the field name. 
    //e.g. if pointer is /grandObject/Object/field
    //JsonPoint.last() will give you /field 
    //remember to take out the / character 
    String fieldName = valueNodePointer.last().toString();
    fieldName = fieldName.replace(Character.toString(JsonPointer.SEPARATOR), StringUtils.EMPTY);
    JsonNode fieldValueNode = parentObjectNode.get(fieldName);

    if(fieldValueNode != null) {
        parentObjectNode.put(fieldName, "NewValue");
    }
}
Мубашар
источник