在Java中比较两个JSON对象。

时间:2020-12-06 05:10:17

I'm looking for a JSON parsing library that supports comparing two JSON objects ignoring child order, specifically for unit testing JSON returning from a web service.

我正在寻找一个JSON解析库,该库支持比较两个不考虑子顺序的JSON对象,特别是用于对从web服务返回的JSON进行单元测试。

Do any of the major JSON libraries support this? The org.json library simply does a reference comparison.

任何主要的JSON库支持这个吗?org。json库只是做一个引用比较。

22 个解决方案

#1


57  

As a general architectural point, I usually advise against letting dependencies on a particular serialization format bleed out beyond your storage/networking layer; thus, I'd first recommend that you consider testing equality between your own application objects rather than their JSON manifestations.

作为一般的体系结构点,我通常建议不要让对特定序列化格式的依赖超出存储/网络层;因此,我首先建议您考虑在自己的应用程序对象之间测试相等性,而不是测试它们的JSON表现。

Having said that, I'm currently a big fan of Jackson which my quick read of their ObjectNode.equals() implementation suggests does the set membership comparison that you want:

话虽如此,我现在还是Jackson的忠实粉丝,我很快地读了一下他们的ObjectNode.equals()实现建议您进行您想要的set成员比较:

public boolean equals(Object o)
{
    if (o == this) return true;
    if (o == null) return false;
    if (o.getClass() != getClass()) {
        return false;
    }
    ObjectNode other = (ObjectNode) o;
    if (other.size() != size()) {
        return false;
    }
    if (_children != null) {
        for (Map.Entry<String, JsonNode> en : _children.entrySet()) {
            String key = en.getKey();
            JsonNode value = en.getValue();

            JsonNode otherValue = other.get(key);

            if (otherValue == null || !otherValue.equals(value)) {
                return false;
            }
        }
    }
    return true;
}

#2


110  

Try Skyscreamer's JSONAssert.

sky screamer JSONAssert的尝试。

Its non-strict mode has two major advantages that make it less brittle:

它的非严格模式有两个主要优点,使它不那么脆弱:

  • Object extensibility (e.g. With an expected value of {id:1}, this would still pass: {id:1,moredata:'x'}.)
  • 对象可扩展性(例如,具有{id:1}的期望值),这仍然会通过:{id:1,moredata:'x'}。
  • Loose array ordering (e.g. ['dog','cat']==['cat','dog'])
  • 宽松的数组排序(例如[‘狗’,‘猫’]= =[“猫”,“狗”])

In strict mode it behaves more like json-lib's test class.

在严格模式下,它的行为更像json-lib的测试类。

A test looks something like this:

测试是这样的:

@Test
public void testGetFriends() {
    JSONObject data = getRESTData("/friends/367.json");
    String expected = "{friends:[{id:123,name:\"Corby Page\"}"
        + ",{id:456,name:\"Solomon Duskis\"}]}";
    JSONAssert.assertEquals(expected, data, false);
}

The parameters in the JSONAssert.assertEquals() call are expectedJSONString, actualDataString, and isStrict.

在JSONAssert.assertEquals()调用中的参数是expectedJSONString、actualDataString和isStrict。

The result messages are pretty clear, which is important when comparing really big JSON objects.

结果消息非常清楚,这在比较大的JSON对象时非常重要。

#3


35  

Using GSON

使用GSON

JsonParser parser = new JsonParser();
JsonElement o1 = parser.parse("{a : {a : 2}, b : 2}");
JsonElement o2 = parser.parse("{b : 2, a : {a : 2}}");
assertEquals(o1, o2);

#4


14  

I would do the following,

我会这样做,

final JSONObject obj1 = /*json*/;
final JSONObject obj2 = /*json*/;

final ObjectMapper mapper = new ObjectMapper();

final JsonNode tree1 = mapper.readTree(obj1.toString());
final JsonNode tree2 = mapper.readTree(obj2.toString());

return tree1.equals(tree2);

#5


11  

You could try using json-lib's JSONAssert class:

您可以尝试使用json-lib的JSONAssert类:

JSONAssert.assertEquals(
  "{foo: 'bar', baz: 'qux'}",
  JSONObject.fromObject("{foo: 'bar', baz: 'xyzzy'}"));

Gives:

给:

junit.framework.ComparisonFailure: objects differed at key [baz]; expected:<[qux]> but was:<[xyzzy]>

#6


9  

If you are already using JUnit, the latest version now employs Hamcrest. It is a generic matching framework (especially useful for unit testing) that can be extended to build new matchers.

如果您已经在使用JUnit,那么最新的版本现在使用Hamcrest。它是一个通用的匹配框架(特别适用于单元测试),可以扩展它来构建新的匹配器。

There is a small open source library called hamcrest-json with JSON-aware matches. It is well documented, tested, and supported. Below are some useful links:

有一个名为hamcrest-json的小型开源库,它具有json感知的匹配。它有很好的文档、测试和支持。以下是一些有用的链接:

Example code using objects from the JSON library org.json.simple:

示例代码使用来自JSON库org.json.simple:

Assert.assertThat(
    jsonObject1.toJSONString(),
    SameJSONAs.sameJSONAs(jsonObject2.toJSONString()));

Optionally, you may (1) allow "any-order" arrays and (2) ignore extra fields.

可选地,您可以(1)允许“任意顺序”数组,(2)忽略额外的字段。

Since there are a variety of JSON libraries for Java (Jackson, GSON, json-lib, etc.), it is useful that hamcrest-json supports JSON text (as java.lang.String), as well as natively supporting objects from Douglas Crockford's JSON library org.json.

由于Java有各种各样的JSON库(Jackson、GSON、JSON -lib等),所以hamcrest-json支持JSON文本(如Java .lang. string),以及来自Douglas Crockford的JSON库org.json的本机支持对象是很有用的。

Finally, if you are not using JUnit, you can use Hamcrest directly for assertions. (I wrote about it here.)

最后,如果不使用JUnit,可以直接使用Hamcrest进行断言。(我在这里写过。)

#7


9  

Use this library: https://github.com/lukas-krecan/JsonUnit

使用这个库:https://github.com/lukas-krecan/JsonUnit

Pom:

Pom:

<dependency>
    <groupId>net.javacrumbs.json-unit</groupId>
    <artifactId>json-unit</artifactId>
    <version>1.5.0</version>
    <scope>test</scope>
</dependency>

IGNORING_ARRAY_ORDER - ignores order in arrays

IGNORING_ARRAY_ORDER——数组中的顺序会被忽略

assertJsonEquals("{\"test\":[1,2,3]}",
                 "{\"test\":  [3,2,1]}",when(IGNORING_ARRAY_ORDER));

#8


8  

You can try JsonUnit. It can compare two JSON objects and report differences. It's built on top of Jackson.

你可以试试JsonUnit。它可以比较两个JSON对象和报告差异。它建在杰克逊之上。

For example

例如

assertJsonEquals("{\"test\":1}", "{\n\"test\": 2\n}");

Results in

结果

java.lang.AssertionError: JSON documents are different:
Different value found in node "test". Expected 1, got 2.

#9


4  

One thing I did and it works wonders is to read both objects into HashMap and then compare with a regular assertEquals(). It will call the equals() method of the hashmaps, which will recursively compare all objects inside (they will be either other hashmaps or some single value object like a string or integer). This was done using Codehaus' Jackson JSON parser.

我所做的一件事很奇妙,那就是将两个对象读入HashMap,然后与常规assertEquals()进行比较。它将调用hashmaps的equals()方法,该方法将递归地比较内部的所有对象(它们要么是其他hashmaps,要么是某个值对象,如字符串或整数)。这是使用Codehaus的Jackson JSON解析器完成的。

assertEquals(mapper.readValue(expectedJson, new TypeReference<HashMap<String, Object>>(){}), mapper.readValue(actualJson, new TypeReference<HashMap<String, Object>>(){}));

A similar approach can be used if the JSON object is an array instead.

如果JSON对象是数组,也可以使用类似的方法。

#10


4  

For org.json I've rolled out my own solution, a method that compares to JSONObject instances. I didn't work with complex JSON objects in that project, so I don't know whether this works in all scenarios. Also, given that I use this in unit tests, I didn't put effort into optimizations. Here it is:

org。我已经推出了我自己的解决方案,该方法可以与JSONObject实例进行比较。我在那个项目中没有使用复杂的JSON对象,所以我不知道在所有的场景中是否都适用。而且,考虑到我在单元测试中使用了它,我没有在优化中投入精力。这里是:

public static boolean jsonObjsAreEqual (JSONObject js1, JSONObject js2) throws JSONException {
    if (js1 == null || js2 == null) {
        return (js1 == js2);
    }

    List<String> l1 =  Arrays.asList(JSONObject.getNames(js1));
    Collections.sort(l1);
    List<String> l2 =  Arrays.asList(JSONObject.getNames(js2));
    Collections.sort(l2);
    if (!l1.equals(l2)) {
        return false;
    }
    for (String key : l1) {
        Object val1 = js1.get(key);
        Object val2 = js2.get(key);
        if (val1 instanceof JSONObject) {
            if (!(val2 instanceof JSONObject)) {
                return false;
            }
            if (!jsonObjsAreEqual((JSONObject)val1, (JSONObject)val2)) {
                return false;
            }
        }

        if (val1 == null) {
            if (val2 != null) {
                return false;
            }
        }  else if (!val1.equals(val2)) {
            return false;
        }
    }
    return true;
}

#11


3  

I'm using this, and works fine for me (with org.json.*):

我正在使用这个,对我来说很好用(使用org.json.*):

package com.project1.helpers;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class JSONUtils {

    public static boolean areEqual(Object ob1, Object ob2) throws JSONException {
        Object obj1Converted = convertJsonElement(ob1);
        Object obj2Converted = convertJsonElement(ob2);
        return obj1Converted.equals(obj2Converted);
    }

    private static Object convertJsonElement(Object elem) throws JSONException {
        if (elem instanceof JSONObject) {
            JSONObject obj = (JSONObject) elem;
            Iterator<String> keys = obj.keys();
            Map<String, Object> jsonMap = new HashMap<>();
            while (keys.hasNext()) {
                String key = keys.next();
                jsonMap.put(key, convertJsonElement(obj.get(key)));
            }
            return jsonMap;
        } else if (elem instanceof JSONArray) {
            JSONArray arr = (JSONArray) elem;
            Set<Object> jsonSet = new HashSet<>();
            for (int i = 0; i < arr.length(); i++) {
                jsonSet.add(convertJsonElement(arr.get(i)));
            }
            return jsonSet;
        } else {
            return elem;
        }
    }
}

#12


2  

I'd take the library at http://json.org/java/, and modify the equals method of JSONObject and JSONArray to do a deep equality test. To make sure that it works regradless of the order of the children, all you need to do is replace the inner map with a TreeMap, or use something like Collections.sort().

我将使用http://json.org/java/的库,修改JSONObject和JSONArray的equals方法,以进行深度平等测试。为了确保它可以不按子节点的顺序重新排列,您需要做的就是用TreeMap替换内部映射,或者使用Collections.sort()之类的方法。

#13


1  

Try this:

试试这个:

public static boolean jsonsEqual(Object obj1, Object obj2) throws JSONException

    {
        if (!obj1.getClass().equals(obj2.getClass()))
        {
            return false;
        }

        if (obj1 instanceof JSONObject)
        {
            JSONObject jsonObj1 = (JSONObject) obj1;

            JSONObject jsonObj2 = (JSONObject) obj2;

            String[] names = JSONObject.getNames(jsonObj1);
            String[] names2 = JSONObject.getNames(jsonObj1);
            if (names.length != names2.length)
            {
                return false;
            }

            for (String fieldName:names)
            {
                Object obj1FieldValue = jsonObj1.get(fieldName);

                Object obj2FieldValue = jsonObj2.get(fieldName);

                if (!jsonsEqual(obj1FieldValue, obj2FieldValue))
                {
                    return false;
                }
            }
        }
        else if (obj1 instanceof JSONArray)
        {
            JSONArray obj1Array = (JSONArray) obj1;
            JSONArray obj2Array = (JSONArray) obj2;

            if (obj1Array.length() != obj2Array.length())
            {
                return false;
            }

            for (int i = 0; i < obj1Array.length(); i++)
            {
                boolean matchFound = false;

                for (int j = 0; j < obj2Array.length(); j++)
                {
                    if (jsonsEqual(obj1Array.get(i), obj2Array.get(j)))
                    {
                        matchFound = true;
                        break;
                    }
                }

                if (!matchFound)
                {
                    return false;
                }
            }
        }
        else
        {
            if (!obj1.equals(obj2))
            {
                return false;
            }
        }

        return true;
    }

#14


1  

You can use zjsonpatch library, which presents the diff information in accordance with RFC 6902 (JSON Patch). Its very easy to use. Please visit its description page for its usage

您可以使用zjsonpatch库,它根据RFC 6902 (JSON Patch)显示diff信息。它很容易使用。请访问它的描述页以了解它的用法

#15


1  

I know it is usually considered only for testing but you could use the Hamcrest JSON comparitorSameJSONAs in Hamcrest JSON.

我知道它通常只用于测试,但是您可以使用Hamcrest JSON中的Hamcrest JSON comparitorSameJSONAs。

Hamcrest JSON SameJSONAs

Hamcrest JSON SameJSONAs

#16


0  

For those like me wanting to do this with Jackson, you can use json-unit.

对于像我这样想和杰克逊合作的人,你可以使用json-unit。

JsonAssert.assertJsonEquals(jsonNode1, jsonNode2);

The errors give useful feedback on the type of mismatch:

这些错误对不匹配类型提供了有用的反馈:

java.lang.AssertionError: JSON documents have different values:
Different value found in node "heading.content[0].tag[0]". Expected 10209, got 10206.

#17


0  

Karate is exactly what you are looking for. Here is an example:

空手道就是你要找的。这是一个例子:

* def myJson = { foo: 'world', hey: 'ho', zee: [5], cat: { name: 'Billie' } }
* match myJson = { cat: { name: 'Billie' }, hey: 'ho', foo: 'world', zee: [5] }

(disclaimer: dev here)

(免责声明:dev)

#18


0  

Nothing else seemed to work quite right, so I wrote this:

其他的似乎都不太对,所以我写了如下:

private boolean jsonEquals(JsonNode actualJson, JsonNode expectJson) {
    if(actualJson.getNodeType() != expectJson.getNodeType()) return false;

    switch(expectJson.getNodeType()) {
    case NUMBER:
        return actualJson.asDouble() == expectJson.asDouble();
    case STRING:
    case BOOLEAN:
        return actualJson.asText().equals(expectJson.asText());
    case OBJECT:
        if(actualJson.size() != expectJson.size()) return false;

        Iterator<String> fieldIterator = actualJson.fieldNames();
        while(fieldIterator.hasNext()) {
            String fieldName = fieldIterator.next();
            if(!jsonEquals(actualJson.get(fieldName), expectJson.get(fieldName))) {
                return false;
            }
        }
        break;
    case ARRAY:
        if(actualJson.size() != expectJson.size()) return false;
        List<JsonNode> remaining = new ArrayList<>();
        expectJson.forEach(remaining::add);
        // O(N^2)   
        for(int i=0; i < actualJson.size(); ++i) {
            boolean oneEquals = false;
            for(int j=0; j < remaining.size(); ++j) {
                if(jsonEquals(actualJson.get(i), remaining.get(j))) {
                    oneEquals = true;
                    remaining.remove(j);
                    break;
                }
            }
            if(!oneEquals) return false;
        }
        break;
    default:
        throw new IllegalStateException();
    }
    return true;
}

#19


0  

Following code will be more helpful to compare two JsonObject, JsonArray, JsonPrimitive and JasonElements.

下面的代码将更有助于比较两个JsonObject、JsonArray、json原语和JasonElements。

private boolean compareJson(JsonElement json1, JsonElement json2) {
        boolean isEqual = true;
        // Check whether both jsonElement are not null
        if (json1 != null && json2 != null) {

            // Check whether both jsonElement are objects
            if (json1.isJsonObject() && json2.isJsonObject()) {
                Set<Entry<String, JsonElement>> ens1 = ((JsonObject) json1).entrySet();
                Set<Entry<String, JsonElement>> ens2 = ((JsonObject) json2).entrySet();
                JsonObject json2obj = (JsonObject) json2;
                if (ens1 != null && ens2 != null) {
                    // (ens2.size() == ens1.size())
                    // Iterate JSON Elements with Key values
                    for (Entry<String, JsonElement> en : ens1) {
                        isEqual = isEqual && compareJson(en.getValue(), json2obj.get(en.getKey()));
                    }
                } else {
                    return false;
                }
            }

            // Check whether both jsonElement are arrays
            else if (json1.isJsonArray() && json2.isJsonArray()) {
                JsonArray jarr1 = json1.getAsJsonArray();
                JsonArray jarr2 = json2.getAsJsonArray();
                if (jarr1.size() != jarr2.size()) {
                    return false;
                } else {
                    int i = 0;
                    // Iterate JSON Array to JSON Elements
                    for (JsonElement je : jarr1) {
                        isEqual = isEqual && compareJson(je, jarr2.get(i));
                        i++;
                    }
                }
            }

            // Check whether both jsonElement are null
            else if (json1.isJsonNull() && json2.isJsonNull()) {
                return true;
            }

            // Check whether both jsonElement are primitives
            else if (json1.isJsonPrimitive() && json2.isJsonPrimitive()) {
                if (json1.equals(json2)) {
                    return true;
                } else {
                    return false;
                }
            } else {
                return false;
            }
        } else if (json1 == null && json2 == null) {
            return true;
        } else {
            return false;
        }
        return isEqual;
    }

#20


0  

For comparing jsons I recommend using JSONCompare: https://github.com/fslev/json-compare

为了比较jsons,我建议使用JSONCompare: https://github.com/fslev/json-compare。

// Compare by regex
String expected = "{\"a\":\".*me.*\"}";
String actual = "{\"a\":\"some text\"}";
JSONCompare.assertEquals(expected, actual);  // True

// Check expected array has no extra elements
String expected = "[1,\"test\",4,\"!.*\"]";
String actual = "[4,1,\"test\"]";
JSONCompare.assertEquals(expected, actual);  // True

// Check expected array has no numbers
String expected = "[\"\\\\\\d+\"]";
String actual = "[\"text\",\"test\"]";
JSONCompare.assertEquals(expected, actual);  // True

// Check expected array has no numbers
String expected = "[\"\\\\\\d+\"]";
String actual = "[2018]";
JSONCompare.assertNotEquals(expected, actual);  // True

#21


-1  

jsonObject implement a comparable interface, try to use collection.sort().

jsonObject实现了一个可比较的接口,尝试使用collection.sort()。

#22


-3  

This Solution for me, work's very good:

这个方案对我来说,工作很好:

try {           
                // Getting The Array "Courses" from json1 & json2   
                Courses1 =json1.getJSONArray(TAG_COURSES1);
                Courses2 = json2.getJSONArray(TAG_COURSES);

                //LOOP FOR JSON1
                for(int i = 0; i < Courses1.length(); i++){
                    //LOOP FOR JSON2
                    for(int ii = 0; ii < Courses2.length(); ii++){
                        JSONObject courses1 = Courses1.getJSONObject(i);
                        JSONObject courses2 = Courses2.getJSONObject(ii);

                        // Storing each json1 item in variable
                        int courseID1 = courses1.getInt(TAG_COURSEID1);
                        Log.e("COURSEID2:", Integer.toString(courseID1));
                        String Rating1 = courses1.getString(TAG_RATING1);
                        int Status1 = courses1.getInt(TAG_STATUS1);
                        Log.e("Status1:", Integer.toString(Status1));      //Put the actual value for Status1 in log.             

                        // Storing each json2 item in variable
                        int courseID2 = courses2.getInt(TAG_COURSEID);
                        Log.e("COURSEID2:", Integer.toString(courseID));   //Put the actual value for CourseID in log
                        String Title2 = courses2.getString(TAG_TITLE);                      
                        String instructor2 = courses2.getString(TAG_INSTRUCTOR);
                        String length2 = courses2.getString(TAG_LENGTH);
                        String rating2 = courses2.getString(TAG_RATING);
                        String subject2 = courses2.getString(TAG_SUBJECT);
                        String description2 = courses2.getString(TAG_DESCRIPTION);

                        //Status1 = 5 from json1; Incomplete, Status1 =-1 Complete 
                        if(Status1 == 5 && courseID2 == courseID1){                                  

                        // creating new HashMap
                        HashMap<String, String> map = new HashMap<String, String>();         
                        //Storing the elements if condition is true.
                        map.put(TAG_COURSEID, Integer.toString(courseID2)); //pend for compare
                        map.put(TAG_TITLE, Title2);
                        map.put(TAG_INSTRUCTOR, instructor2);
                        map.put(TAG_LENGTH, length2);
                        map.put(TAG_RATING, rating2);
                        map.put(TAG_SUBJECT, subject2); //show it
                        map.put(TAG_DESCRIPTION, description2);

                        //adding HashList to ArrayList
                        contactList.add(map);
                        }//if
                    }//for2 (json2)
                } //for1 (json1)                
            }//Try

Hope this help others.

希望这次帮助别人。

#1


57  

As a general architectural point, I usually advise against letting dependencies on a particular serialization format bleed out beyond your storage/networking layer; thus, I'd first recommend that you consider testing equality between your own application objects rather than their JSON manifestations.

作为一般的体系结构点,我通常建议不要让对特定序列化格式的依赖超出存储/网络层;因此,我首先建议您考虑在自己的应用程序对象之间测试相等性,而不是测试它们的JSON表现。

Having said that, I'm currently a big fan of Jackson which my quick read of their ObjectNode.equals() implementation suggests does the set membership comparison that you want:

话虽如此,我现在还是Jackson的忠实粉丝,我很快地读了一下他们的ObjectNode.equals()实现建议您进行您想要的set成员比较:

public boolean equals(Object o)
{
    if (o == this) return true;
    if (o == null) return false;
    if (o.getClass() != getClass()) {
        return false;
    }
    ObjectNode other = (ObjectNode) o;
    if (other.size() != size()) {
        return false;
    }
    if (_children != null) {
        for (Map.Entry<String, JsonNode> en : _children.entrySet()) {
            String key = en.getKey();
            JsonNode value = en.getValue();

            JsonNode otherValue = other.get(key);

            if (otherValue == null || !otherValue.equals(value)) {
                return false;
            }
        }
    }
    return true;
}

#2


110  

Try Skyscreamer's JSONAssert.

sky screamer JSONAssert的尝试。

Its non-strict mode has two major advantages that make it less brittle:

它的非严格模式有两个主要优点,使它不那么脆弱:

  • Object extensibility (e.g. With an expected value of {id:1}, this would still pass: {id:1,moredata:'x'}.)
  • 对象可扩展性(例如,具有{id:1}的期望值),这仍然会通过:{id:1,moredata:'x'}。
  • Loose array ordering (e.g. ['dog','cat']==['cat','dog'])
  • 宽松的数组排序(例如[‘狗’,‘猫’]= =[“猫”,“狗”])

In strict mode it behaves more like json-lib's test class.

在严格模式下,它的行为更像json-lib的测试类。

A test looks something like this:

测试是这样的:

@Test
public void testGetFriends() {
    JSONObject data = getRESTData("/friends/367.json");
    String expected = "{friends:[{id:123,name:\"Corby Page\"}"
        + ",{id:456,name:\"Solomon Duskis\"}]}";
    JSONAssert.assertEquals(expected, data, false);
}

The parameters in the JSONAssert.assertEquals() call are expectedJSONString, actualDataString, and isStrict.

在JSONAssert.assertEquals()调用中的参数是expectedJSONString、actualDataString和isStrict。

The result messages are pretty clear, which is important when comparing really big JSON objects.

结果消息非常清楚,这在比较大的JSON对象时非常重要。

#3


35  

Using GSON

使用GSON

JsonParser parser = new JsonParser();
JsonElement o1 = parser.parse("{a : {a : 2}, b : 2}");
JsonElement o2 = parser.parse("{b : 2, a : {a : 2}}");
assertEquals(o1, o2);

#4


14  

I would do the following,

我会这样做,

final JSONObject obj1 = /*json*/;
final JSONObject obj2 = /*json*/;

final ObjectMapper mapper = new ObjectMapper();

final JsonNode tree1 = mapper.readTree(obj1.toString());
final JsonNode tree2 = mapper.readTree(obj2.toString());

return tree1.equals(tree2);

#5


11  

You could try using json-lib's JSONAssert class:

您可以尝试使用json-lib的JSONAssert类:

JSONAssert.assertEquals(
  "{foo: 'bar', baz: 'qux'}",
  JSONObject.fromObject("{foo: 'bar', baz: 'xyzzy'}"));

Gives:

给:

junit.framework.ComparisonFailure: objects differed at key [baz]; expected:<[qux]> but was:<[xyzzy]>

#6


9  

If you are already using JUnit, the latest version now employs Hamcrest. It is a generic matching framework (especially useful for unit testing) that can be extended to build new matchers.

如果您已经在使用JUnit,那么最新的版本现在使用Hamcrest。它是一个通用的匹配框架(特别适用于单元测试),可以扩展它来构建新的匹配器。

There is a small open source library called hamcrest-json with JSON-aware matches. It is well documented, tested, and supported. Below are some useful links:

有一个名为hamcrest-json的小型开源库,它具有json感知的匹配。它有很好的文档、测试和支持。以下是一些有用的链接:

Example code using objects from the JSON library org.json.simple:

示例代码使用来自JSON库org.json.simple:

Assert.assertThat(
    jsonObject1.toJSONString(),
    SameJSONAs.sameJSONAs(jsonObject2.toJSONString()));

Optionally, you may (1) allow "any-order" arrays and (2) ignore extra fields.

可选地,您可以(1)允许“任意顺序”数组,(2)忽略额外的字段。

Since there are a variety of JSON libraries for Java (Jackson, GSON, json-lib, etc.), it is useful that hamcrest-json supports JSON text (as java.lang.String), as well as natively supporting objects from Douglas Crockford's JSON library org.json.

由于Java有各种各样的JSON库(Jackson、GSON、JSON -lib等),所以hamcrest-json支持JSON文本(如Java .lang. string),以及来自Douglas Crockford的JSON库org.json的本机支持对象是很有用的。

Finally, if you are not using JUnit, you can use Hamcrest directly for assertions. (I wrote about it here.)

最后,如果不使用JUnit,可以直接使用Hamcrest进行断言。(我在这里写过。)

#7


9  

Use this library: https://github.com/lukas-krecan/JsonUnit

使用这个库:https://github.com/lukas-krecan/JsonUnit

Pom:

Pom:

<dependency>
    <groupId>net.javacrumbs.json-unit</groupId>
    <artifactId>json-unit</artifactId>
    <version>1.5.0</version>
    <scope>test</scope>
</dependency>

IGNORING_ARRAY_ORDER - ignores order in arrays

IGNORING_ARRAY_ORDER——数组中的顺序会被忽略

assertJsonEquals("{\"test\":[1,2,3]}",
                 "{\"test\":  [3,2,1]}",when(IGNORING_ARRAY_ORDER));

#8


8  

You can try JsonUnit. It can compare two JSON objects and report differences. It's built on top of Jackson.

你可以试试JsonUnit。它可以比较两个JSON对象和报告差异。它建在杰克逊之上。

For example

例如

assertJsonEquals("{\"test\":1}", "{\n\"test\": 2\n}");

Results in

结果

java.lang.AssertionError: JSON documents are different:
Different value found in node "test". Expected 1, got 2.

#9


4  

One thing I did and it works wonders is to read both objects into HashMap and then compare with a regular assertEquals(). It will call the equals() method of the hashmaps, which will recursively compare all objects inside (they will be either other hashmaps or some single value object like a string or integer). This was done using Codehaus' Jackson JSON parser.

我所做的一件事很奇妙,那就是将两个对象读入HashMap,然后与常规assertEquals()进行比较。它将调用hashmaps的equals()方法,该方法将递归地比较内部的所有对象(它们要么是其他hashmaps,要么是某个值对象,如字符串或整数)。这是使用Codehaus的Jackson JSON解析器完成的。

assertEquals(mapper.readValue(expectedJson, new TypeReference<HashMap<String, Object>>(){}), mapper.readValue(actualJson, new TypeReference<HashMap<String, Object>>(){}));

A similar approach can be used if the JSON object is an array instead.

如果JSON对象是数组,也可以使用类似的方法。

#10


4  

For org.json I've rolled out my own solution, a method that compares to JSONObject instances. I didn't work with complex JSON objects in that project, so I don't know whether this works in all scenarios. Also, given that I use this in unit tests, I didn't put effort into optimizations. Here it is:

org。我已经推出了我自己的解决方案,该方法可以与JSONObject实例进行比较。我在那个项目中没有使用复杂的JSON对象,所以我不知道在所有的场景中是否都适用。而且,考虑到我在单元测试中使用了它,我没有在优化中投入精力。这里是:

public static boolean jsonObjsAreEqual (JSONObject js1, JSONObject js2) throws JSONException {
    if (js1 == null || js2 == null) {
        return (js1 == js2);
    }

    List<String> l1 =  Arrays.asList(JSONObject.getNames(js1));
    Collections.sort(l1);
    List<String> l2 =  Arrays.asList(JSONObject.getNames(js2));
    Collections.sort(l2);
    if (!l1.equals(l2)) {
        return false;
    }
    for (String key : l1) {
        Object val1 = js1.get(key);
        Object val2 = js2.get(key);
        if (val1 instanceof JSONObject) {
            if (!(val2 instanceof JSONObject)) {
                return false;
            }
            if (!jsonObjsAreEqual((JSONObject)val1, (JSONObject)val2)) {
                return false;
            }
        }

        if (val1 == null) {
            if (val2 != null) {
                return false;
            }
        }  else if (!val1.equals(val2)) {
            return false;
        }
    }
    return true;
}

#11


3  

I'm using this, and works fine for me (with org.json.*):

我正在使用这个,对我来说很好用(使用org.json.*):

package com.project1.helpers;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class JSONUtils {

    public static boolean areEqual(Object ob1, Object ob2) throws JSONException {
        Object obj1Converted = convertJsonElement(ob1);
        Object obj2Converted = convertJsonElement(ob2);
        return obj1Converted.equals(obj2Converted);
    }

    private static Object convertJsonElement(Object elem) throws JSONException {
        if (elem instanceof JSONObject) {
            JSONObject obj = (JSONObject) elem;
            Iterator<String> keys = obj.keys();
            Map<String, Object> jsonMap = new HashMap<>();
            while (keys.hasNext()) {
                String key = keys.next();
                jsonMap.put(key, convertJsonElement(obj.get(key)));
            }
            return jsonMap;
        } else if (elem instanceof JSONArray) {
            JSONArray arr = (JSONArray) elem;
            Set<Object> jsonSet = new HashSet<>();
            for (int i = 0; i < arr.length(); i++) {
                jsonSet.add(convertJsonElement(arr.get(i)));
            }
            return jsonSet;
        } else {
            return elem;
        }
    }
}

#12


2  

I'd take the library at http://json.org/java/, and modify the equals method of JSONObject and JSONArray to do a deep equality test. To make sure that it works regradless of the order of the children, all you need to do is replace the inner map with a TreeMap, or use something like Collections.sort().

我将使用http://json.org/java/的库,修改JSONObject和JSONArray的equals方法,以进行深度平等测试。为了确保它可以不按子节点的顺序重新排列,您需要做的就是用TreeMap替换内部映射,或者使用Collections.sort()之类的方法。

#13


1  

Try this:

试试这个:

public static boolean jsonsEqual(Object obj1, Object obj2) throws JSONException

    {
        if (!obj1.getClass().equals(obj2.getClass()))
        {
            return false;
        }

        if (obj1 instanceof JSONObject)
        {
            JSONObject jsonObj1 = (JSONObject) obj1;

            JSONObject jsonObj2 = (JSONObject) obj2;

            String[] names = JSONObject.getNames(jsonObj1);
            String[] names2 = JSONObject.getNames(jsonObj1);
            if (names.length != names2.length)
            {
                return false;
            }

            for (String fieldName:names)
            {
                Object obj1FieldValue = jsonObj1.get(fieldName);

                Object obj2FieldValue = jsonObj2.get(fieldName);

                if (!jsonsEqual(obj1FieldValue, obj2FieldValue))
                {
                    return false;
                }
            }
        }
        else if (obj1 instanceof JSONArray)
        {
            JSONArray obj1Array = (JSONArray) obj1;
            JSONArray obj2Array = (JSONArray) obj2;

            if (obj1Array.length() != obj2Array.length())
            {
                return false;
            }

            for (int i = 0; i < obj1Array.length(); i++)
            {
                boolean matchFound = false;

                for (int j = 0; j < obj2Array.length(); j++)
                {
                    if (jsonsEqual(obj1Array.get(i), obj2Array.get(j)))
                    {
                        matchFound = true;
                        break;
                    }
                }

                if (!matchFound)
                {
                    return false;
                }
            }
        }
        else
        {
            if (!obj1.equals(obj2))
            {
                return false;
            }
        }

        return true;
    }

#14


1  

You can use zjsonpatch library, which presents the diff information in accordance with RFC 6902 (JSON Patch). Its very easy to use. Please visit its description page for its usage

您可以使用zjsonpatch库,它根据RFC 6902 (JSON Patch)显示diff信息。它很容易使用。请访问它的描述页以了解它的用法

#15


1  

I know it is usually considered only for testing but you could use the Hamcrest JSON comparitorSameJSONAs in Hamcrest JSON.

我知道它通常只用于测试,但是您可以使用Hamcrest JSON中的Hamcrest JSON comparitorSameJSONAs。

Hamcrest JSON SameJSONAs

Hamcrest JSON SameJSONAs

#16


0  

For those like me wanting to do this with Jackson, you can use json-unit.

对于像我这样想和杰克逊合作的人,你可以使用json-unit。

JsonAssert.assertJsonEquals(jsonNode1, jsonNode2);

The errors give useful feedback on the type of mismatch:

这些错误对不匹配类型提供了有用的反馈:

java.lang.AssertionError: JSON documents have different values:
Different value found in node "heading.content[0].tag[0]". Expected 10209, got 10206.

#17


0  

Karate is exactly what you are looking for. Here is an example:

空手道就是你要找的。这是一个例子:

* def myJson = { foo: 'world', hey: 'ho', zee: [5], cat: { name: 'Billie' } }
* match myJson = { cat: { name: 'Billie' }, hey: 'ho', foo: 'world', zee: [5] }

(disclaimer: dev here)

(免责声明:dev)

#18


0  

Nothing else seemed to work quite right, so I wrote this:

其他的似乎都不太对,所以我写了如下:

private boolean jsonEquals(JsonNode actualJson, JsonNode expectJson) {
    if(actualJson.getNodeType() != expectJson.getNodeType()) return false;

    switch(expectJson.getNodeType()) {
    case NUMBER:
        return actualJson.asDouble() == expectJson.asDouble();
    case STRING:
    case BOOLEAN:
        return actualJson.asText().equals(expectJson.asText());
    case OBJECT:
        if(actualJson.size() != expectJson.size()) return false;

        Iterator<String> fieldIterator = actualJson.fieldNames();
        while(fieldIterator.hasNext()) {
            String fieldName = fieldIterator.next();
            if(!jsonEquals(actualJson.get(fieldName), expectJson.get(fieldName))) {
                return false;
            }
        }
        break;
    case ARRAY:
        if(actualJson.size() != expectJson.size()) return false;
        List<JsonNode> remaining = new ArrayList<>();
        expectJson.forEach(remaining::add);
        // O(N^2)   
        for(int i=0; i < actualJson.size(); ++i) {
            boolean oneEquals = false;
            for(int j=0; j < remaining.size(); ++j) {
                if(jsonEquals(actualJson.get(i), remaining.get(j))) {
                    oneEquals = true;
                    remaining.remove(j);
                    break;
                }
            }
            if(!oneEquals) return false;
        }
        break;
    default:
        throw new IllegalStateException();
    }
    return true;
}

#19


0  

Following code will be more helpful to compare two JsonObject, JsonArray, JsonPrimitive and JasonElements.

下面的代码将更有助于比较两个JsonObject、JsonArray、json原语和JasonElements。

private boolean compareJson(JsonElement json1, JsonElement json2) {
        boolean isEqual = true;
        // Check whether both jsonElement are not null
        if (json1 != null && json2 != null) {

            // Check whether both jsonElement are objects
            if (json1.isJsonObject() && json2.isJsonObject()) {
                Set<Entry<String, JsonElement>> ens1 = ((JsonObject) json1).entrySet();
                Set<Entry<String, JsonElement>> ens2 = ((JsonObject) json2).entrySet();
                JsonObject json2obj = (JsonObject) json2;
                if (ens1 != null && ens2 != null) {
                    // (ens2.size() == ens1.size())
                    // Iterate JSON Elements with Key values
                    for (Entry<String, JsonElement> en : ens1) {
                        isEqual = isEqual && compareJson(en.getValue(), json2obj.get(en.getKey()));
                    }
                } else {
                    return false;
                }
            }

            // Check whether both jsonElement are arrays
            else if (json1.isJsonArray() && json2.isJsonArray()) {
                JsonArray jarr1 = json1.getAsJsonArray();
                JsonArray jarr2 = json2.getAsJsonArray();
                if (jarr1.size() != jarr2.size()) {
                    return false;
                } else {
                    int i = 0;
                    // Iterate JSON Array to JSON Elements
                    for (JsonElement je : jarr1) {
                        isEqual = isEqual && compareJson(je, jarr2.get(i));
                        i++;
                    }
                }
            }

            // Check whether both jsonElement are null
            else if (json1.isJsonNull() && json2.isJsonNull()) {
                return true;
            }

            // Check whether both jsonElement are primitives
            else if (json1.isJsonPrimitive() && json2.isJsonPrimitive()) {
                if (json1.equals(json2)) {
                    return true;
                } else {
                    return false;
                }
            } else {
                return false;
            }
        } else if (json1 == null && json2 == null) {
            return true;
        } else {
            return false;
        }
        return isEqual;
    }

#20


0  

For comparing jsons I recommend using JSONCompare: https://github.com/fslev/json-compare

为了比较jsons,我建议使用JSONCompare: https://github.com/fslev/json-compare。

// Compare by regex
String expected = "{\"a\":\".*me.*\"}";
String actual = "{\"a\":\"some text\"}";
JSONCompare.assertEquals(expected, actual);  // True

// Check expected array has no extra elements
String expected = "[1,\"test\",4,\"!.*\"]";
String actual = "[4,1,\"test\"]";
JSONCompare.assertEquals(expected, actual);  // True

// Check expected array has no numbers
String expected = "[\"\\\\\\d+\"]";
String actual = "[\"text\",\"test\"]";
JSONCompare.assertEquals(expected, actual);  // True

// Check expected array has no numbers
String expected = "[\"\\\\\\d+\"]";
String actual = "[2018]";
JSONCompare.assertNotEquals(expected, actual);  // True

#21


-1  

jsonObject implement a comparable interface, try to use collection.sort().

jsonObject实现了一个可比较的接口,尝试使用collection.sort()。

#22


-3  

This Solution for me, work's very good:

这个方案对我来说,工作很好:

try {           
                // Getting The Array "Courses" from json1 & json2   
                Courses1 =json1.getJSONArray(TAG_COURSES1);
                Courses2 = json2.getJSONArray(TAG_COURSES);

                //LOOP FOR JSON1
                for(int i = 0; i < Courses1.length(); i++){
                    //LOOP FOR JSON2
                    for(int ii = 0; ii < Courses2.length(); ii++){
                        JSONObject courses1 = Courses1.getJSONObject(i);
                        JSONObject courses2 = Courses2.getJSONObject(ii);

                        // Storing each json1 item in variable
                        int courseID1 = courses1.getInt(TAG_COURSEID1);
                        Log.e("COURSEID2:", Integer.toString(courseID1));
                        String Rating1 = courses1.getString(TAG_RATING1);
                        int Status1 = courses1.getInt(TAG_STATUS1);
                        Log.e("Status1:", Integer.toString(Status1));      //Put the actual value for Status1 in log.             

                        // Storing each json2 item in variable
                        int courseID2 = courses2.getInt(TAG_COURSEID);
                        Log.e("COURSEID2:", Integer.toString(courseID));   //Put the actual value for CourseID in log
                        String Title2 = courses2.getString(TAG_TITLE);                      
                        String instructor2 = courses2.getString(TAG_INSTRUCTOR);
                        String length2 = courses2.getString(TAG_LENGTH);
                        String rating2 = courses2.getString(TAG_RATING);
                        String subject2 = courses2.getString(TAG_SUBJECT);
                        String description2 = courses2.getString(TAG_DESCRIPTION);

                        //Status1 = 5 from json1; Incomplete, Status1 =-1 Complete 
                        if(Status1 == 5 && courseID2 == courseID1){                                  

                        // creating new HashMap
                        HashMap<String, String> map = new HashMap<String, String>();         
                        //Storing the elements if condition is true.
                        map.put(TAG_COURSEID, Integer.toString(courseID2)); //pend for compare
                        map.put(TAG_TITLE, Title2);
                        map.put(TAG_INSTRUCTOR, instructor2);
                        map.put(TAG_LENGTH, length2);
                        map.put(TAG_RATING, rating2);
                        map.put(TAG_SUBJECT, subject2); //show it
                        map.put(TAG_DESCRIPTION, description2);

                        //adding HashList to ArrayList
                        contactList.add(map);
                        }//if
                    }//for2 (json2)
                } //for1 (json1)                
            }//Try

Hope this help others.

希望这次帮助别人。