Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Java中测试两个JSON对象是否相等忽略子顺序_Java_Json_Junit - Fatal编程技术网

在Java中测试两个JSON对象是否相等忽略子顺序

在Java中测试两个JSON对象是否相等忽略子顺序,java,json,junit,Java,Json,Junit,我正在寻找一个JSON解析库,它支持比较两个忽略子顺序的JSON对象,特别是对从web服务返回的JSON进行单元测试 有任何主要的JSON库支持这一点吗?org.json库只是做了一个引用比较。我将在上获取该库,并修改JSONObject和JSONArray的equals方法来进行深度相等性测试。为了确保它的工作不受子对象顺序的影响,您只需将内部映射替换为TreeMap,或者使用类似于Collections.sort()的方法,我将使用库,并修改JSONObject和JSONArray的equa

我正在寻找一个JSON解析库,它支持比较两个忽略子顺序的JSON对象,特别是对从web服务返回的JSON进行单元测试


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

我将在上获取该库,并修改JSONObject和JSONArray的
equals
方法来进行深度相等性测试。为了确保它的工作不受子对象顺序的影响,您只需将内部映射替换为
TreeMap
,或者使用类似于
Collections.sort()

的方法,我将使用库,并修改JSONObject和JSONArray的
equals
方法来进行深度相等性测试。为了确保它的工作不受子对象顺序的影响,只需将内部映射替换为
TreeMap
,或者使用类似
Collections.sort()的内容作为一般架构点,我通常建议不要让对特定序列化格式的依赖超出存储/网络层;因此,我首先建议您考虑在自己的应用程序对象之间测试相等性,而不是测试它们的JSON表示形式。
话虽如此,我目前是一个超级粉丝,我快速阅读了他们的实现后,发现你想要的集合成员比较:

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;
}
公共布尔等于(对象o)
{
如果(o==this)返回true;
如果(o==null)返回false;
如果(o.getClass()!=getClass()){
返回false;
}
ObjectNode other=(ObjectNode)o;
如果(其他.size()!=size()){
返回false;
}
如果(_children!=null){
对于(Map.Entry en:_children.entrySet()){
String key=en.getKey();
JsonNode value=en.getValue();
JsonNode otherValue=other.get(key);
如果(otherValue==null | |!otherValue.equals(value)){
返回false;
}
}
}
返回true;
}

作为一个总体架构要点,我通常建议不要让对特定序列化格式的依赖超出存储/网络层;因此,我首先建议您考虑在自己的应用程序对象之间测试相等性,而不是测试它们的JSON表示形式。 话虽如此,我目前是一个超级粉丝,我快速阅读了他们的实现后,发现你想要的集合成员比较:

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;
}
公共布尔等于(对象o)
{
如果(o==this)返回true;
如果(o==null)返回false;
如果(o.getClass()!=getClass()){
返回false;
}
ObjectNode other=(ObjectNode)o;
如果(其他.size()!=size()){
返回false;
}
如果(_children!=null){
对于(Map.Entry en:_children.entrySet()){
String key=en.getKey();
JsonNode value=en.getValue();
JsonNode otherValue=other.get(key);
如果(otherValue==null | |!otherValue.equals(value)){
返回false;
}
}
}
返回true;
}

您可以尝试使用json库的类:

JSONAssert.assertEquals(
“{foo:'bar',baz:'qux'}”,
fromObject(“{foo:'bar',baz:'xyzy'}”)
);
给出:

junit.framework.ComparisonFailure: objects differed at key [baz]; expected:<[qux]> but was:<[xyzzy]>
junit.framework.ComparisonFailure:objects在键[baz]处不同;预期:但是:

您可以尝试使用json库的类:

JSONAssert.assertEquals(
“{foo:'bar',baz:'qux'}”,
fromObject(“{foo:'bar',baz:'xyzy'}”)
);
给出:

junit.framework.ComparisonFailure: objects differed at key [baz]; expected:<[qux]> but was:<[xyzzy]>
junit.framework.ComparisonFailure:objects在键[baz]处不同;预期:但是:

我做了一件事,它非常有效,那就是将这两个对象读入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>>(){}));
assertEquals(mapper.readValue(expectedJson,newtypereference(){})、mapper.readValue(actualJson,newtypereference(){}));

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

我做了一件非常有用的事情,将这两个对象读入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>>(){}));
assertEquals(mapper.readValue(expectedJson,newtypereference(){})、mapper.readValue(actualJson,newtypereference(){}));
如果JSON对象是数组,则可以使用类似的方法。

使用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);
编辑:因为实例方法
JsonParser.parse
已被弃用。您必须使用静态方法
JsonParser.parseString

JsonElement o1 = JsonParser.parseString("{a : {a : 2}, b : 2}");
JsonElement o2 = JsonParser.parseString("{b : 2, a : {a : 2}}");
assertEquals(o1, o2);
使用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);
编辑:因为实例方法
JsonParser.parse
已被弃用。您必须使用静态方法
JsonParser.parseString

JsonElement o1 = JsonParser.parseString("{a : {a : 2}, b : 2}");
JsonElement o2 = JsonParser.parseString("{b : 2, a : {a : 2}}");
assertEquals(o1, o2);
你可以试试。它可以比较两个JSON对象并报告差异。它建在杰克逊的顶上

比如说

assertThatJson("{\"test\":1}").isEqualTo("{\n\"test\": 2\n}");
导致

java.lang.AssertionError: JSON documents are different:
Different value found in node "test". Expected 1, got 2.
你可以试试。它可以比较两个JSON对象并报告差异。它建在杰克逊的顶上

比如说

assertThatJson("{\"test\":1}").isEqualTo("{\n\"test\": 2\n}");
导致

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

其非严格模式有两个主要优点,使其不易脆化:

  • 对象可扩展性(例如,如果预期值为{id:1},则仍将传递:{id:1,moredata:'x'})
  • 松散数组排序(例如,['dog','cat']==['cat','dog'])
在严格模式下,它的行为更像json库的测试类

测试如下所示:

@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);
}
* def myJson = { foo: 'world', hey: 'ho', zee: [5], cat: { name: 'Billie' } } * match myJson = { cat: { name: 'Billie' }, hey: 'ho', foo: 'world', zee: [5] }
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;
}
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;
    }
// 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
JSON.areEqual(json1, json2); //using BlobCity Java Commons
json1 = new JSONObject("{...}");
json2 = new JSONObject("{...}");
json1.toMap().equals(json2.toMap());
Map<Object, Object> resMap = gson.fromJson(res, new TypeToken<Map<Object, Object>>() {}.getType());
Map<Object, Object> expectedMap = gson.fromJson(expected, new TypeToken<Map<Object, Object>>() {}.getType());
Assertions.assertThat(resMap).usingRecursiveComparison().isEqualTo(expectedMap);
import com.fasterxml.jackson.*

boolean compareJsonPojo(Object pojo1, Object pojo2) {
        try {
            ObjectMapper mapper = new ObjectMapper();
            String str1 = mapper.writeValueAsString(pojo1);
            String str2 = mapper.writeValueAsString(pojo2);
            return mapper.readTree(str1).equals(mapper.readTree(str2));
        } catch (JsonProcessingException e) {
            throw new AssertionError("Error comparing JSON objects: " + e.getMessage());
        }
    }
java.lang.AssertionError: someObject.someArray[1].someInternalObject2.value
Expected: 456
     got: 4567
@Test
void test() throws Exception {

    final String json1 =
        "{" +
        "  'someObject': {" +
        "    'someArray': [" +
        "      {" +
        "        'someInternalObject': {" +
        "          'value': '123'" +
        "        }" +
        "      }," +
        "      {" +
        "        'someInternalObject2': {" +
        "          'value': '456'" +
        "        }" +
        "      }" +
        "    ]" +
        "  }" +
        "}";

    final String json2 =
        "{" +
        "  'someObject': {" +
        "    'someArray': [" +
        "      {" +
        "        'someInternalObject': {" +
        "          'value': '123'" +
        "        }" +
        "      }," +
        "      {" +
        "        'someInternalObject2': {" +
        "          'value': '4567'" +
        "        }" +
        "      }" +
        "    ]" +
        "  }" +
        "}";

    new JsonExpectationsHelper().assertJsonEqual(json1, json2, true);
}