杰克逊更新部分对象

时间:2014-12-15 22:38:28

标签: java json jackson jackson-modules

这就是我想要做的。假设我有2个json输入。

首先

{"testArr":[{"name":"name1"},{"name":"name2"}]}

第二

{"testArr":[{"name":"name1Changed"}]}

我有课程

class test{
 public String name;
}

class runner{
  public ArrayList<test> testArr;
  public String firstJson;
  public String secondJson;

  public void runProj(){
    ObjectMapper mapper = new ObjectMapper();
    //This one is correct works just fine
    testArr = mapper.readValue(firstJson, ITBTeam.class);

    //Now I want to update just value of first element of array and 
    //tryed to use this function but this one will trim my array
     mapper.readerForUpdating(testArr).readValue(secondJson);
  }

}

所以在这之后我得到了

{"testArr":[{"name":"name1Changed"}]}

我想要的地方

{"testArr":[{"name":"name1Changed"},{"name":"name2"}]}

如果我遗漏了杰克逊的某些内容或者没有这样的功能,请告诉我。我需要自己编写。

因为没有直接的对话来做我想要的就是我为json节点写的做同样的事情。合并/覆盖节点和merge / overwriteArray的两个函数。这可以通过传递2个json Nodes希望如果有人在寻找类似的东西会有所帮助

 public static JsonNode mergeNode(JsonNode mainNode, JsonNode updateNode) {
    Iterator<String> fieldNames = updateNode.fieldNames();
    while (fieldNames.hasNext()) {

        String fieldName = fieldNames.next();
        JsonNode jsonNode = mainNode.get(fieldName);
        // if field exists and is an embedded object
        if (null != jsonNode && (jsonNode.isObject())) {
            mergeNode(jsonNode, updateNode.get(fieldName));
            // if field exists and is an embedded array
        } else if (null != jsonNode && (jsonNode.isArray())) {
            mergeArray(jsonNode, updateNode.get(fieldName));
        } else {
            // Overwrite field node               
            ((ObjectNode) mainNode).set(fieldName, updateNode.get(fieldName));
        }
    }
    return mainNode;
}

public static void mergeArray(JsonNode mainNode, JsonNode updateNode) {
    //Loops over array and adds items if they dont exist 
    //or updates existing value if it is not an object
    for (int i = 0; i < updateNode.size(); i++) {
        JsonNode jsonNode = mainNode.get(i);
        if (null != jsonNode && jsonNode.isObject()) {
            mergeNode(jsonNode, updateNode.get(i));
        } else if (null != jsonNode && (jsonNode.isArray())) {
            mergeArray(jsonNode, updateNode.get(i));
        } else if (null == jsonNode) {
            ((ArrayNode) mainNode).add(updateNode.get(i));
        } else {
            ((ArrayNode) mainNode).set(i, updateNode.get(i));
        }
    }       
}

2 个答案:

答案 0 :(得分:0)

您最好的选择是将这两个文档都读为JsonNode,然后使用您想到的逻辑遍历和更新第一个文档。不幸的是,有许多可能的方法可能需要合并 - 例如,在JSON数组的情况下,应该选择一个或两个;或者它们是否应该被连接;或者条目是否应该被索引覆盖(这是你想要的) - 所以杰克逊没有这种处理的功能。

答案 1 :(得分:0)

现在您可以使用JSON-Patch https://github.com/fge/json-patch来合并两个JSON对象/节点

    // With Jackson
    final JsonMergePatch patch = mapper.readValue(in, JsonMergePatch.class);
    // With a JsonNode
    final JsonMergePatch patch = JsonMergePatch.fromJson(node);

    // orig is also a JsonNode
    final JsonNode patched = patch.apply(orig);