Comparing two JSON objects irrespective of json array sequence in them using java

Viewed 22

Is there any way in java to compare two json objects and print the changes/differences?

I have tried with "Flat-map utility" which is flattening and also comparing the json objects, however diff failed in case of json array elements in different orders in two json objects.

e.g

JSON 1

{
"name":"Jack",
"student_ID":1,
"subject":[
{
"marks":50,
"subjectId":"PHY",
"subjectName":"Physics"
},
{
"marks":60,
"subjectId":"CHE",
"subjectName":"Chemistry"
}
]
}

JSON 2

{
"name":"Jack",
"student_ID":1,
"subject":[
{
"marks":60,
"subjectId":"CHE",
"subjectName":"Chemistry"
},{
"marks":50,
"subjectId":"PHY",
"subjectName":"Physics"
}
]
}

json diff shows the Two jsons are mismatched.. Logically those are identical..

Is there a good way of json matching and comparing in java?

code used:

public class compareUtil 
{
    public static void main(String[] args) throws IOException, UnresolvedDatasetException, ParseException 
{
        // TODO Auto-generated method stub
        
        String baselineFolderPath = "input//jsonBaseline"; 
        String regressionfolderPath = "input//jsonRegression";
        
        String fileToCompare = "sampleJson1_simple.json";
        
        String baselineFile = baselineFolderPath + "//" + fileToCompare;
        String regressionFile = regressionfolderPath + "//" + fileToCompare;
                
        InputStream getBaselineJsonFile = new FileInputStream(baselineFile);
        InputStream getRegressionJsonFile = new FileInputStream(regressionFile);
                        
        ObjectMapper mapper = new ObjectMapper();
        TypeReference<HashMap<String, Object>> type = new TypeReference<HashMap<String, Object>>() {};

        Map<String, Object> baselineMap = mapper.readValue(getBaselineJsonFile, type);
        Map<String, Object> regressionMap = mapper.readValue(getRegressionJsonFile, type);
        
        MapDifference<String, Object> differenceNormal = Maps.difference(baselineMap, regressionMap);
        System.out.println(differenceNormal);
        
        Map<String, Object> baselineFlatMap = FlatMapUtil.flatten(baselineMap);
        Map<String, Object> regressionFlatMap = FlatMapUtil.flatten(regressionMap);
                
        MapDifference<String, Object> difference = Maps.difference(baselineFlatMap, regressionFlatMap);

        System.out.println("The diff "+difference);
        
        System.out.println("Entries only on the baseline json\n--------------------------");
        difference.entriesOnlyOnLeft()
                  .forEach((key, value) -> System.out.println(key + ": " + value));

        System.out.println("\n\nEntries only on the regression json\n--------------------------");
        difference.entriesOnlyOnRight()
                  .forEach((key, value) -> System.out.println(key + ": " + value));

        System.out.println("\n\nEntries differing (baseline, regression)\n--------------------------");
        difference.entriesDiffering()
                  .forEach((key, value) -> System.out.println(key + ": " + value));
     
    }

    
}

------------------------------------------------------------------------------------------------



public final class FlatMapUtil {
    private FlatMapUtil() {
        throw new AssertionError("No instances for you!");
    }
    public static Map<String, Object> flatten(Map<String, Object> map) {
        return map.entrySet().stream()
                .flatMap(FlatMapUtil::flatten)
                .collect(LinkedHashMap::new, (m, e) -> m.put("/" + e.getKey(), e.getValue()), LinkedHashMap::putAll);
    }
    private static Stream<Map.Entry<String, Object>> flatten(Map.Entry<String, Object> entry) {
        
        if (entry == null) {
            return Stream.empty();
        }

        if (entry.getValue() instanceof Map<?, ?>) {
            return ((Map<?, ?>) entry.getValue()).entrySet().stream()
                    .flatMap(e -> flatten(new AbstractMap.SimpleEntry<>(entry.getKey() + "/" + e.getKey(), e.getValue())));
        }

        if (entry.getValue() instanceof List<?>) {
            List<?> list = (List<?>) entry.getValue();
            return IntStream.range(0, list.size())
                    .mapToObj(i -> new AbstractMap.SimpleEntry<String, Object>(entry.getKey() + "/" + i, list.get(i)))
                    .flatMap(FlatMapUtil::flatten);
        }

        return Stream.of(entry);
    }
}
0 Answers
Related