Is there a Java library that can “diff” two Objects?

前端 未结 7 1033
长发绾君心
长发绾君心 2020-11-28 03:35

Is there a Java utility library that is analogous to the Unix program diff, but for Objects? I\'m looking for something that can compare two objects of the same type and ge

相关标签:
7条回答
  • 2020-11-28 03:56

    http://javers.org is library that does exacly what you need: has methods like compare(Object leftGraph, Object rightGraph) returning the Diff object. Diff contains a list of changes (ReferenceChange, ValueChange, PropertyChange) e.g.

    given:
    DummyUser user =  dummyUser("id").withSex(FEMALE).build();
    DummyUser user2 = dummyUser("id").withSex(MALE).build();
    Javers javers = JaversTestBuilder.newInstance()
    
    when:
    Diff diff = javers.compare(user, user2)
    
    then:
    diff.changes.size() == 1
    ValueChange change = diff.changes[0]
    change.leftValue == FEMALE
    change.rightValue == MALE
    

    It can handle cycles in graphs.

    In addition you can get Snapshot of any graph object. Javers has JSON serializers and deserializers to snapshot, and changes so you can easily save them in database. With this library you can easily implement a module for auditing.

    0 讨论(0)
  • 2020-11-28 03:57

    Yes, the java-util library has a GraphComparator class that will compare two Java Object Graphs. It returns the difference as a List of deltas. The GraphComparator also permits you to merge (apply) the deltas as well. This code only has dependencies on the JDK, no other libraries.

    0 讨论(0)
  • 2020-11-28 04:03

    Maybe this will help, depending on where you use this code, it could be useful or problematic. Tested this code.

        /**
     * @param firstInstance
     * @param secondInstance
     */
    protected static void findMatchingValues(SomeClass firstInstance,
            SomeClass secondInstance) {
        try {
            Class firstClass = firstInstance.getClass();
            Method[] firstClassMethodsArr = firstClass.getMethods();
    
            Class secondClass = firstInstance.getClass();
            Method[] secondClassMethodsArr = secondClass.getMethods();
    
    
            for (int i = 0; i < firstClassMethodsArr.length; i++) {
                Method firstClassMethod = firstClassMethodsArr[i];
                // target getter methods.
                if(firstClassMethod.getName().startsWith("get") 
                        && ((firstClassMethod.getParameterTypes()).length == 0)
                        && (!(firstClassMethod.getName().equals("getClass")))
                ){
    
                    Object firstValue;
                        firstValue = firstClassMethod.invoke(firstInstance, null);
    
                    logger.info(" Value "+firstValue+" Method "+firstClassMethod.getName());
    
                    for (int j = 0; j < secondClassMethodsArr.length; j++) {
                        Method secondClassMethod = secondClassMethodsArr[j];
                        if(secondClassMethod.getName().equals(firstClassMethod.getName())){
                            Object secondValue = secondClassMethod.invoke(secondInstance, null);
                            if(firstValue.equals(secondValue)){
                                logger.info(" Values do match! ");
                            }
                        }
                    }
                }
            }
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
    }
    
    0 讨论(0)
  • 2020-11-28 04:09

    A simpler approach to quickly tell you if two objects are different would be is to use the apache commons library

        BeanComparator lastNameComparator = new BeanComparator("lname");
        logger.info(" Match "+bc.compare(firstInstance, secondInstance));
    
    0 讨论(0)
  • 2020-11-28 04:11

    All the Javers library has support to only Java 7, I was in a situation since I want this to be used for a Java 6 project so I happened to take the source and change in a way it works for Java 6 below is the github code.

    https://github.com/sand3sh/javers-forJava6

    Jar link: https://github.com/sand3sh/javers-forJava6/blob/master/build/javers-forjava6.jar

    I have only changed the Java 7 supported '<>' inherent cast conversions to Java 6 support I dont gurantee all the functionalities will work since I have commented few unnecessary code for me it works for all custom objects comparision.

    0 讨论(0)
  • 2020-11-28 04:12

    Might be a little late, but I was in the same situation like you and ended up creating my own library for exactly your use-case. Since I was forced to come up with a solution myself, I decided to release it on Github, to spare others the hard work. You can find it here: https://github.com/SQiShER/java-object-diff

    --- Edit ---

    Here is a little usage example based on the OPs code:

    SomeClass a = new SomeClass();
    SomeClass b = new SomeClass();
    
    a.setProp1("A");
    a.setProp2("X");
    
    b.setProp1("B");
    b.setProp2("X");
    
    DiffNode diff = ObjectDifferBuilder.buildDefault().compare(a, b);
    
    assert diff.hasChanges();
    assert diff.childCount() == 1;
    assert diff.getChild('prop1').getState() == DiffNode.State.CHANGED;
    
    0 讨论(0)
提交回复
热议问题