如何在Java中修改JsonNode?

173

我需要在Java中更改JSON属性的值,我可以正确获取值,但我无法修改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
            }
        }
    }

最好的方式是什么?


5
您可以将JsonNode转换为Java Map,例如:resultMap = mapper.convertValue(aJsonNode, Map.class);,在Map中修改数据,然后再将该Map转换回JsonNode。就这样说了。 - MikeJRamsey56
7个回答

298

JsonNode 是不可变的,旨在进行解析操作。但是,它可以转换为允许更改的 ObjectNode(和 ArrayNode):

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

对于一个数组,你可以使用:

((ObjectNode)jsonNode).putArray("arrayName").add(object.ge‌​tValue());

8
尝试更改数值类型中的值时,我遇到了这个异常: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”。 - mulya
@balboa_21 改变一个整数并没有太多意义。这有点像我把4改成9,然后全世界的人都开始数1、2、3、9、5、6、7、8。你想要做的是改变对象上的字段以包含不同的整数,所以你需要将对象提升为ObjectNode,并操作相关字段。 - MichaelRom
1
"ObjectNode.put()"已过时,可以使用"set"代替。 - a3765910
1
错误:"ObjectNode无法解析为类型" - john k

14

在已接受答案的评论中,一些人点赞了另一个答案并且他们在尝试强制转换为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

代码示例,目标是修改NodeANode1的子节点subfield

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@


7
我认为你可以将其转换为ObjectNode,并使用put方法。就像这样: ObjectNode o = (ObjectNode) jsonNode; o.put("value", "NO");

6
@Sharon-Ben-Asher的回答是可以的,但在我的情况下,我需要使用以下代码来处理数组:
((ArrayNode) jsonNode).add("value");

2

为了让那些可能无法完全理解整个过程的人理解,下面的代码对我有效,可以找到一个字段并更新它。

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

2

为了设置值,您需要获取ObjectNode类型的对象。 请参考此链接


0
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> nodeMap = mapper.convertValue(jsonNode, new TypeReference<Map<String, Object>>(){});
nodeMap.put("key", "value");
jsonNode = mapper.convertValue(nodeMap, JsonNode.class);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接