All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.dnastack.audit.diff.JsonPatchDiffProvider Maven / Gradle / Ivy

The newest version!
package com.dnastack.audit.diff;

import com.dnastack.audit.ObjectMapperFactory;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.flipkart.zjsonpatch.DiffFlags;
import com.flipkart.zjsonpatch.JsonDiff;
import com.flipkart.zjsonpatch.JsonPatch;

import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;

public class JsonPatchDiffProvider {

    private final static Pattern pattern = Pattern.compile("\\d+");

    private static final ObjectMapper objectMapper = ObjectMapperFactory.create();

    public static List getDiff(Object source, Object target) {
        JsonNode jsonSource = source != null ? objectMapper.convertValue(source, JsonNode.class) : null;
        JsonNode jsonTarget = target != null ? objectMapper.convertValue(target, JsonNode.class) : null;

        JsonNode patch = JsonDiff.asJson(jsonSource, jsonTarget, DiffFlags.dontNormalizeOpIntoMoveAndCopy().clone());
        TypeReference> type = new TypeReference<>() {};
        List jsonDiffPatches = objectMapper.convertValue(patch, type);

        JsonNode intermediateObject = jsonSource;
        for (JsonPatchDiff patchDiff : jsonDiffPatches) {
            if ("remove".equalsIgnoreCase(patchDiff.getOp())) {
                patchDiff.setOriginalValue(intermediateObject.at(patchDiff.getPath()));
                patchDiff.setValue(null);
            }
            if ("replace".equalsIgnoreCase(patchDiff.getOp())) {
                patchDiff.setOriginalValue(intermediateObject.at(patchDiff.getPath()));
            }

            if ("add".equalsIgnoreCase(patchDiff.getOp()) && intermediateObject == null) {
                intermediateObject = objectMapper.convertValue(patchDiff.getValue(), JsonNode.class);
                patchDiff.setContext(prepareContext(intermediateObject, patchDiff.getPath()));
            } else if ("remove".equalsIgnoreCase(patchDiff.getOp()) && "".equalsIgnoreCase(patchDiff.getPath())) {
                patchDiff.setContext(prepareContext(intermediateObject, patchDiff.getPath()));
                intermediateObject = objectMapper.nullNode();
            } else {
                intermediateObject = JsonPatch.apply(objectMapper.convertValue(List.of(patchDiff), JsonNode.class), intermediateObject);
                patchDiff.setContext(prepareContext(intermediateObject, patchDiff.getPath()));
            }
        }
        return jsonDiffPatches;
    }

    private static JsonNode prepareContext(JsonNode object, String patchPath) {
        JsonNode context = object.deepCopy();
        if (context.at(patchPath).isValueNode()) { // TRIM unnecessary array(s) of parent
            context.at(patchPath.substring(0, patchPath.lastIndexOf("/"))).fields().forEachRemaining((entry) -> {
                if (entry.getValue().isArray()) {
                    ((ArrayNode) entry.getValue()).removeAll();
                }
            });
        } else if (context.at(patchPath).isObject()) { // TRIM unnecessary array(s)
            context.at(patchPath).fields().forEachRemaining((entry) -> {
                if (entry.getValue().isArray()) {
                    ((ArrayNode) entry.getValue()).removeAll();
                }
            });
        }
        String[] pathArray = patchPath.split("/");
        for (int i=0; i




© 2015 - 2025 Weber Informatics LLC | Privacy Policy