private JsonNode mergeTranslations(JsonNode original, JsonNode overlay) {

        // If we are at a leaf node, the result of merging is simply the overlay
        if (!overlay.isObject() || original == null)
            return overlay;

        // Create mutable copy of original
        ObjectNode newNode = JsonNodeFactory.instance.objectNode();
        Iterator<String> fieldNames = original.fieldNames();
        while (fieldNames.hasNext()) {
            String fieldName = fieldNames.next();
            newNode.set(fieldName, original.get(fieldName));
        }

        // Merge each field
        fieldNames = overlay.fieldNames();
        while (fieldNames.hasNext()) {
            String fieldName = fieldNames.next();
            newNode.set(fieldName, mergeTranslations(original.get(fieldName), overlay.get(fieldName)));
        }

        return newNode;

    }
Merges the given JSON objects. Any leaf node in overlay will overwrite
the corresponding path in original.

@param original
    The original JSON object to which changes should be applied.

@param overlay
    The JSON object containing changes that should be applied.

@return
    The newly constructed JSON object that is the result of merging
    original and overlay.
guacamole/src/main/java/org/apache/guacamole/extension/LanguageResourceService.java