Como modificar JsonNode em Java?

109

Preciso alterar o valor de um atributo JSON em Java, posso obter o valor corretamente, mas não consegui modificar o JSON.

aqui está o código abaixo

  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
            }
        }
    }

Qual é a melhor maneira de fazer isso?

mstfdz
fonte
1
Você pode converter o JsonNode em um mapa Java, por exemplo, resultMap = mapper.convertValue(aJsonNode, Map.class);modificá-lo no mapa e, em seguida, alterar esse mapa de volta para um JsonNode. Apenas dizendo.
MikeJRamsey56

Respostas:

195

JsonNodeé imutável e destina-se à operação de análise. No entanto, pode ser lançado em ObjectNode(e ArrayNode) que permitem mutações:

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

Para uma matriz, você pode usar:

((ObjectNode)jsonNode).putArray("arrayName").add(object.ge‌​tValue());
Sharon Ben Asher
fonte
4
tentei para um tipo numérico em que preciso alterar o valor. Recebi esta exceção: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
Você precisa tentar "IntNode"
mulya de
6

Adicionando uma resposta como alguns outros votaram positivamente nos comentários da resposta aceita, eles estão recebendo esta exceção ao tentar lançar para ObjectNode (eu incluído):

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

A solução é obter o nó 'pai' e realizar uma putsubstituição efetiva de todo o nó, independentemente do tipo de nó original.

Se você precisar "modificar" o nó usando o valor existente do nó:

  1. get o valor / matriz do JsonNode
  2. Faça sua modificação nesse valor / array
  3. Prossiga para chamar puto pai.

Código, onde o objetivo é modificar subfield, que é o nó filho de NodeAe 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");

Créditos:

Tirei essa inspiração daqui , graças a wassgreen @

matrixanomaly
fonte
5

A resposta @Sharon-Ben-Asher está ok.

Mas, no meu caso, para um array, preciso usar:

((ArrayNode) jsonNode).add("value");
Alejandro
fonte
4

Acho que você pode apenas lançar em ObjectNode e usar o putmétodo. Como isso

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

Xdsasdf
fonte
2

Você precisa obter o ObjectNodeobjeto de tipo para definir os valores. Dê uma olhada nisso

Eugen Halca
fonte
0

Apenas para compreender os outros que podem não entender todo o quadro, seguir o código funciona para mim encontrar um campo e depois atualizá-lo

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");
    }
}
Mubashar
fonte