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

com.redhat.lightblue.util.JsonCompare Maven / Gradle / Ivy

There is a newer version: 2.18.0
Show newest version
/*
 Copyright 2013 Red Hat, Inc. and/or its affiliates.

 This file is part of lightblue.

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program.  If not, see .
 */
package com.redhat.lightblue.util;

import java.util.Map;
import java.util.Iterator;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.node.ValueNode;
import com.fasterxml.jackson.databind.node.NullNode;
import java.io.FileReader;

/**
 * Compares two json documents and builds an list of all changes
 *
 * Json containers (objects and arrays) are compared recursively. The
 * comparison algorithm works like this:
 *
 * Objects: A field-by-field comparison is done. If a field exists in
 * the first document but not in the second, that field is removed. If
 * a field exists in the second document but not the first, that field
 * is added. If a field exists in both documents with different
 * values, that field is modified.
 *
 * Arrays: There are two possible algorithms to compare arrays. If
 * array elements contain a unique identifier (which is defined by the
 * caller), then array elelements of the first and the second document
 * are matched using the unique identifiers of array elements. Then
 * each matching array element is compared to generate the detailed
 * difference. If array elements don't have unique identifiers, then
 * each element of the first array is compared to each element of the
 * second array, and the elements with minimal number of changes are
 * associated. Elements that are too different from each other are not
 * associated.
 *
 * Differences: 
 *
 * An Addition denotes a new field or array element. Addition.field1
 * is null, meaning the field does not exist in document1, and
 * Addition.field2 denotes the new field, or array element.
 *
 * A Removal denotes a removed field or array element. Removal.field1
 * denotes the element in document1, and Removal.field2 is null.
 *
 * A Modification denotes a content modification of a field, or array
 * element. Both field1 and field2 are non-null, and set to the name
 * of the modified field.
 *
 * A Move denotes an array element move. field1 denotes the old index
 * of the array element, and field2 denotes the new index.
 *
 * If new elements are added to an array, or existing elements are
 * removed, the addition and removal appear as diff, and any node that
 * shifted during the operation appears within a Move.
 */
public class JsonCompare extends DocComparator {

    public class DefaultIdentityExtractor implements IdentityExtractor {
        private final Path[] fields;

        public DefaultIdentityExtractor(ArrayIdentityFields fields) {
            this.fields=fields.getFields();
        }

        @Override
        public Object getIdentity(JsonNode element) {
            JsonNode[] nodes=new JsonNode[fields.length];
            for(int i=0;i> getFields(ObjectNode node) {
        return node.fields();
    }

    @Override
    protected boolean hasField(ObjectNode value,String field) {
        return value.has(field);
    }

    @Override
    protected JsonNode getField(ObjectNode value,String field) {
        return value.get(field);
    }

    @Override
    protected IdentityExtractor getArrayIdentityExtractorImpl(ArrayIdentityFields fields) {
        return new DefaultIdentityExtractor(fields);
    }

    @Override
    protected JsonNode getElement(ArrayNode value,int index) {
        return value.get(index);
    }

    @Override
    protected int size(ArrayNode value) {
        return value.size();
    }

    public static void main(String[] args) throws Exception {
        try (FileReader fr1 = new java.io.FileReader(args[0]);
                FileReader fr2 = new java.io.FileReader(args[1])) {
            JsonNode f1=JsonUtils.json(fr1,false);
            JsonNode f2=JsonUtils.json(fr2,false);
            JsonCompare cmp=new JsonCompare();
            DocComparator.Difference diff=cmp.compareNodes(f1,f2);
            System.out.println(diff);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy