我正在寻找一个JSON解析库,支持比较忽略子顺序的两个JSON对象,特别是用于从web服务返回的单元测试JSON。
有任何主要的JSON库支持这一点吗?org。Json库只是做一个引用比较。
我正在寻找一个JSON解析库,支持比较忽略子顺序的两个JSON对象,特别是用于从web服务返回的单元测试JSON。
有任何主要的JSON库支持这一点吗?org。Json库只是做一个引用比较。
当前回答
ModelAssert - https://github.com/webcompere/model-assert可以做到这一点。默认情况下,它更喜欢JSON是有序的,但它可以使用对象键和数组元素的宽松顺序:
assertJson(json1)
.where().keysInAnyOrder().arrayInAnyOrder()
.isEqualTo(json2);
这个断言是AssertJ风格的——即使用流畅的DSL。ModelAssert还可以用于使用相同的DSL构建Hamcrest或Mockito匹配器。
Json可以是字符串、文件、Jackson JsonNode,甚至是自发转换为Json进行比较的POJO。
还支持yml。
其他回答
我正在使用这个,并为我工作良好(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;
}
}
}
下面是使用Jackson ObjectMapper的代码。要了解更多,请阅读这篇文章。
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());
}
}
ModelAssert - https://github.com/webcompere/model-assert可以做到这一点。默认情况下,它更喜欢JSON是有序的,但它可以使用对象键和数组元素的宽松顺序:
assertJson(json1)
.where().keysInAnyOrder().arrayInAnyOrder()
.isEqualTo(json2);
这个断言是AssertJ风格的——即使用流畅的DSL。ModelAssert还可以用于使用相同的DSL构建Hamcrest或Mockito匹配器。
Json可以是字符串、文件、Jackson JsonNode,甚至是自发转换为Json进行比较的POJO。
还支持yml。
试试这个:
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;
}
作为一个通用的架构点,我通常建议不要让对特定序列化格式的依赖超出您的存储/网络层;因此,我首先建议您考虑测试您自己的应用程序对象之间的相等性,而不是它们的JSON表示。
话已这么说,我目前是Jackson的忠实粉丝,我快速阅读了他们的ObjectNode.equals()实现,建议进行你想要的集合成员比较:
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;
}