48 votes

Fusion de deux documents JSON à l'aide de Jackson

Est-il possible de fusionner deux documents JSON avec la bibliothèque Jackson JSON ? J'utilise essentiellement le mappeur Jackson avec de simples cartes Java.

J'ai essayé de rechercher dans la documentation de Google et Jackson mais je n'ai rien trouvé.

65voto

Arne Points 540

Inspiré par la réponse de StaxMans, j'ai implémenté cette méthode de fusion.

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

J'espère que cela aide quelqu'un.

17voto

Jay Khatwani Points 329

Inspiré par la réponse d'Arn. Le modifier pour ajouter le cas où un nœud peut contenir un tableau de nœuds.

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

6voto

mig-foxbat Points 1145

Vous trouverez ci-dessous une implémentation en Scala. Les nœuds source et cible sont principalement commutatifs, sauf lorsqu'une branche existe à la fois dans la source et la cible.

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

3voto

moh sajid khan Points 31

Si quelqu'un souhaite simplement ajouter deux objets JsonNode ou plus dans un seul JsonNode, cela peut être une approche :

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X