package org.gcube.portlets.user.geoportaldataentry.server.json; import java.io.IOException; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; /** * This class provides methods to merge two json of any nested level into a * single json. * * copied from: https://github.com/hemantsonu20/json-merge * * @maintainer updated by Francesco Mangiacrapa at ISTI-CNR * francesco.mangiacrapa@isti.cnr.it * * Apr 21, 2023 */ public class JsonMerge { private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); /** * The Enum MERGE_OPTION. * * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it * * Apr 21, 2023 */ public static enum MERGE_OPTION { MERGE, REPLACE } /** * Method to merge two json objects into single json object. * *
* It merges two json of any nested level into a single json following below * logic. *
** When keys are same at some level, following table denotes what value will be * used. *
*Src / Target | *JSON Value | *JSON Array | *JSON Object | *
---|---|---|---|
JSON Value1 | *Src | *Src | *Src | *
JSON Array | *Src2 | *Merge | *Src | *
JSON Object | *Src | *Src | *Merge3 | *
Src
value will be
* copied.Src
and
* Target
values will be merged.* Source Json *
* ** {@code * { * "name": "json-merge-src" * } * } **
* Target Json *
* ** {@code * { * "name": "json-merge-target" * } * } **
* Output *
* ** {@code * { * "name": "json-merge-src" * } * } ** *
* Source Json *
* ** {@code * { * "level1": { * "key1": "SrcValue1" * } * } * } **
* Target Json *
* ** {@code * { * "level1": { * "key1": "targetValue1", * "level2": { * "key2": "value2" * } * } * } * } **
* Output *
* ** {@code * { * "level1": { * "key1": "SrcValue1", * "level2": { * "key2": "value2" * } * } * } * } ** * @param srcJsonStr source json string * @param targetJsonStr target json string * @param option the option * @return merged json as a string */ public static String merge(String srcJsonStr, String targetJsonStr, MERGE_OPTION option) { try { if (option == null) option = MERGE_OPTION.MERGE; JsonNode srcNode = OBJECT_MAPPER.readTree(srcJsonStr); JsonNode targetNode = OBJECT_MAPPER.readTree(targetJsonStr); JsonNode result = merge(srcNode, targetNode, option); return OBJECT_MAPPER.writeValueAsString(result); } catch (IOException e) { throw new JsonMergeException("Unable to merge json", e); } } /** * Merge. * * @param srcNode the src node * @param targetNode the target node * @param option the option * @return the json node */ public static JsonNode merge(JsonNode srcNode, JsonNode targetNode, MERGE_OPTION option) { if (option == null) option = MERGE_OPTION.MERGE; // if both nodes are object node, merged object node is returned if (srcNode.isObject() && targetNode.isObject()) { return merge((ObjectNode) srcNode, (ObjectNode) targetNode, option); } // if both nodes are array node, merged array node is returned if (srcNode.isArray() && targetNode.isArray()) { return mergeArray((ArrayNode) srcNode, (ArrayNode) targetNode, option); } // special case when src node is null if (srcNode.isNull()) { return targetNode; } return srcNode; } /** * Merge. * * @param srcNode the src node * @param targetNode the target node * @param option the option * @return the object node */ public static ObjectNode merge(ObjectNode srcNode, ObjectNode targetNode, MERGE_OPTION option) { ObjectNode result = OBJECT_MAPPER.createObjectNode(); Iterator