使用Jackson合并两个JSON文档

gpfsuwkq  于 2022-12-15  发布在  其他
关注(0)|答案(7)|浏览(195)

可以用JacksonJSON库合并两个JSON文档吗?我基本上是用JacksonMap器和简单的JavaMap。
我试着在谷歌和Jackson的文档中搜索,但什么也没找到。

rsaldnfx

rsaldnfx1#

受StaxMans回答的启发,我实现了这个合并方法。

public static JsonNode merge(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 (jsonNode != null && jsonNode.isObject()) {
            merge(jsonNode, updateNode.get(fieldName));
        }
        else {
            if (mainNode instanceof ObjectNode) {
                // Overwrite field
                JsonNode value = updateNode.get(fieldName);
                ((ObjectNode) mainNode).put(fieldName, value);
            }
        }

    }

    return mainNode;
}

希望这能帮到什么人。

zaq34kh6

zaq34kh62#

一种方法是这样使用ObjectReader

MyBean defaults = objectMapper.readValue(defaultJson, MyBean.class);
ObjectReader updater = objectMapper.readerForUpdating(defaults);
MyBean merged = updater.readValue(overridesJson);

它将合并来自两个源的数据。这只做一个浅副本,即不对包含的对象做递归合并。
否则,您可能需要将JSON作为树(JsonNode)读取,循环遍历内容并手动合并。这通常是有意义的,因为合并规则并不是微不足道的,每个人都有自己的合并工作方式。

编辑:(2017年4月3日)

根据@费尔南多·科雷亚的评论,实际上在即将到来的Jackson2.9(将于2017年4月或5月发布)中添加了一个新的feature,它最终允许深度合并。

5uzkadbs

5uzkadbs3#

受Arn答案的启发,对它进行了编辑,添加了一个节点可能包含一个节点数组的情况。

public static JsonNode merge(JsonNode mainNode, JsonNode updateNode) {

    Iterator<String> fieldNames = updateNode.fieldNames();

    while (fieldNames.hasNext()) {
        String updatedFieldName = fieldNames.next();
        JsonNode valueToBeUpdated = mainNode.get(updatedFieldName);
        JsonNode updatedValue = updateNode.get(updatedFieldName);

        // If the node is an @ArrayNode
        if (valueToBeUpdated != null && valueToBeUpdated.isArray() && 
            updatedValue.isArray()) {
            // running a loop for all elements of the updated ArrayNode
            for (int i = 0; i < updatedValue.size(); i++) {
                JsonNode updatedChildNode = updatedValue.get(i);
                // Create a new Node in the node that should be updated, if there was no corresponding node in it
                // Use-case - where the updateNode will have a new element in its Array
                if (valueToBeUpdated.size() <= i) {
                    ((ArrayNode) valueToBeUpdated).add(updatedChildNode);
                }
                // getting reference for the node to be updated
                JsonNode childNodeToBeUpdated = valueToBeUpdated.get(i);
                merge(childNodeToBeUpdated, updatedChildNode);
            }
        // if the Node is an @ObjectNode
        } else if (valueToBeUpdated != null && valueToBeUpdated.isObject()) {
            merge(valueToBeUpdated, updatedValue);
        } else {
            if (mainNode instanceof ObjectNode) {
                ((ObjectNode) mainNode).replace(updatedFieldName, updatedValue);
            }
        }
    }
    return mainNode;
}
xeufq47z

xeufq47z4#

下面是Scala的一个实现。源节点和目标节点通常是可交换的,除非分支同时存在于源节点和目标节点中。

def mergeYamlObjects(source: ObjectNode, target: ObjectNode, overwrite: Boolean = true): ObjectNode = {
    if (target == null)
      source
    else if (source == null)
      target
    else {
      val result = source.deepCopy
      val fieldlist = source.fieldNames.asScala.toList ++ target.fieldNames.asScala.toList
      for (item <- fieldlist) {
        if (!(source has item)) {
          result put(item, target get item)
        } else {
          if ((source get item).isValueNode) {
            if (target has item)
              if (overwrite)
                result.put(item, target get item)
          } else {
            result.put(item, mergeYamlObjects(source.get(item).asInstanceOf[ObjectNode],
              target.get(item).asInstanceOf[ObjectNode], overwrite = overwrite))
          }
        }
      }
      result
    }
  }
yh2wf1be

yh2wf1be5#

如果有人只是想将两个或多个JsonNode对象添加到一个JsonNode中,可以使用以下方法:

ArrayNode arrayNode = objectMapper.createArrayNode();
arrayNode.add(firstJsonNode);
arrayNode.add(secondJsonNode);
arrayNode.add(thirdJsonNode);

JsonNode root = JsonNodeFactory.instance.objectNode();
((ObjectNode) root).put("", arrayNode);
System.out.println("merged array node #: " + root);
l2osamch

l2osamch6#

下面是将两个JSON树合并为一个的完整实现。希望对您有所帮助:)

/**
 * Merge two JSON tree into one i.e mergedInTo.
 *
 * @param toBeMerged
 * @param mergedInTo
 */
public static void merge(JsonNode toBeMerged, JsonNode mergedInTo) {
    Iterator<Map.Entry<String, JsonNode>> incomingFieldsIterator = toBeMerged.fields();
    Iterator<Map.Entry<String, JsonNode>> mergedIterator = mergedInTo.fields();

    while (incomingFieldsIterator.hasNext()) {
        Map.Entry<String, JsonNode> incomingEntry = incomingFieldsIterator.next();

        JsonNode subNode = incomingEntry.getValue();

        if (subNode.getNodeType().equals(JsonNodeType.OBJECT)) {
            boolean isNewBlock = true;
            mergedIterator = mergedInTo.fields();
            while (mergedIterator.hasNext()) {
                Map.Entry<String, JsonNode> entry = mergedIterator.next();
                if (entry.getKey().equals(incomingEntry.getKey())) {
                    merge(incomingEntry.getValue(), entry.getValue());
                    isNewBlock = false;
                }
            }
            if (isNewBlock) {
                ((ObjectNode) mergedInTo).replace(incomingEntry.getKey(), incomingEntry.getValue());
            }
        } else if (subNode.getNodeType().equals(JsonNodeType.ARRAY)) {
            boolean newEntry = true;
            mergedIterator = mergedInTo.fields();
            while (mergedIterator.hasNext()) {
                Map.Entry<String, JsonNode> entry = mergedIterator.next();
                if (entry.getKey().equals(incomingEntry.getKey())) {
                    updateArray(incomingEntry.getValue(), entry);
                    newEntry = false;
                }
            }
            if (newEntry) {
                ((ObjectNode) mergedInTo).replace(incomingEntry.getKey(), incomingEntry.getValue());
            }
        }
        ValueNode valueNode = null;
        JsonNode incomingValueNode = incomingEntry.getValue();
        switch (subNode.getNodeType()) {
            case STRING:
                valueNode = new TextNode(incomingValueNode.textValue());
                break;
            case NUMBER:
                valueNode = new IntNode(incomingValueNode.intValue());
                break;
            case BOOLEAN:
                valueNode = BooleanNode.valueOf(incomingValueNode.booleanValue());
        }
        if (valueNode != null) {
            updateObject(mergedInTo, valueNode, incomingEntry);
        }
    }
}

private static void updateArray(JsonNode valueToBePlaced, Map.Entry<String, JsonNode> toBeMerged) {
    toBeMerged.setValue(valueToBePlaced);
}

private static void updateObject(JsonNode mergeInTo, ValueNode valueToBePlaced,
                                 Map.Entry<String, JsonNode> toBeMerged) {
    boolean newEntry = true;
    Iterator<Map.Entry<String, JsonNode>> mergedIterator = mergeInTo.fields();
    while (mergedIterator.hasNext()) {
        Map.Entry<String, JsonNode> entry = mergedIterator.next();
        if (entry.getKey().equals(toBeMerged.getKey())) {
            newEntry = false;
            entry.setValue(valueToBePlaced);
        }
    }
    if (newEntry) {
        ((ObjectNode) mergeInTo).replace(toBeMerged.getKey(), toBeMerged.getValue());
    }
}
fxnxkyjh

fxnxkyjh7#

如果您的目标是连接两个JSON,我发现最简单的方法如下(考虑到您已经准备好了两个ObjecNode):

ObjectMapper mapper = new ObjectMapper();

// Dummy objects to concatenate
Map<String, Object> map = new HashMap();
map.put("k", "v");

Map<String, Object> secondMap = new HashMap();
secondMap.put("secondK", "secondV");

//Transforming Objects into ObjectNode
ObjectNode firstObjectNode = mapper.convertValue(map, ObjectNode.class);
ObjectNode secondObjectNode = mapper.convertValue(secondMap, ObjectNode.class);

//Concatenating secondObjectNode into firstObjectNode
firstObjectNode.setAll(secondObjectNode);

//Output will be: {"k":"v","secondK":"secondV"}
System.out.println(firstObjectNode);

希望能有所帮助

相关问题