REST Assured 74 - Problem With JSONassert While Ignoring Fields From JSON Documents

REST Assured 系列汇总 之 REST Assured 74 - Problem With JSONassert While Ignoring Fields From JSON Documents

介绍

JSONassert 库用来比较 JSON 文档,比较文档时,我们会自定义一些忽略的字段,当忽略的字段不存在时,将发生什么?

简单的 JSON object 中没有被忽略的字段

我们知道 how to ignore fields from a comparison in JSON Objects ,但是有可能这些忽略的字段在 JSON Objects中不存在。特别是对动态的 JSON Objects,我不知道字段总是存在的。我们可以通过一个例子来了解一下。

请注意:当一个字段不存在于第二个 JSON object会出现问题,而字段不存在于第一个 JSON Object时不会出错。

JSON Object 1

{
    
    
  "id": 1,
  "first_name": "Amod",
  "last_name": "Mahajan",
  "married": false,
  "salary": 123.45
}

JSON Object 2

{
    
    
  "id": 1,
  "first_name": "Amod",
  "last_name": "Mahajan",
  "married": false
}

上面两个 JSON Objects, “Salary” 不存在于第二个 JSON Object 中。要忽略 “Salary” 字段,假设这个字段可能存在,可能不存在。现实场景中,董事会的 “Salary” 是不可见的。

import org.json.JSONException;
import org.skyscreamer.jsonassert.Customization;
import org.skyscreamer.jsonassert.JSONAssert;
import org.skyscreamer.jsonassert.JSONCompareMode;
import org.skyscreamer.jsonassert.comparator.CustomComparator;
import org.skyscreamer.jsonassert.comparator.JSONComparator;
 
public class IgnoringFieldsFromSimpleJsonObjectsNonExistence {
    
    
	
	public static void main(String[] args) throws JSONException {
    
    
		
		String s1 = "{\r\n" + 
				"  \"id\": 1,\r\n" + 
				"  \"first_name\": \"Amod\",\r\n" + 
				"  \"last_name\": \"Mahajan\",\r\n" + 
				"  \"married\": false,\r\n" + 
				"  \"salary\": 123.45\r\n" + 
				"}";
		
		String s2 = "{\r\n" + 
				"  \"id\": 1,\r\n" + 
				"  \"first_name\": \"Amod\",\r\n" + 
				"  \"last_name\": \"Mahajan\",\r\n" + 
				"  \"married\": false\r\n" + 
				"}";
		
		JSONComparator com = new CustomComparator(JSONCompareMode.LENIENT, 
				new Customization("salary", (o1, o2) -> true));
		
		JSONAssert.assertEquals(s1, s2, com);
		
	}
 
}

结果:
在这里插入图片描述
可以看出,当被忽略的字段不存在于第二个 JSON object 中会有 AssertionError。这不是我们想要的,如果字段被忽略,就应该忽略检查是否存在这个问题。

没有直接的方法解决这个问题,我们需要重载方法。

解决方法

如果你调试代码,就会发现有一个 “AbstractComparator” 抽象类中有一个 “checkJsonObjectKeysExpectedInActual()” 方法,这个方法被内部调用了,默认的实现是这样的:

protected void checkJsonObjectKeysExpectedInActual(String prefix, JSONObject expected, JSONObject actual, JSONCompareResult result) throws JSONException {
    
    
        Set<String> expectedKeys = getKeys(expected);
        for (String key : expectedKeys) {
    
    
            Object expectedValue = expected.get(key);
            if (actual.has(key)) {
    
    
                Object actualValue = actual.get(key);
                compareValues(qualify(prefix, key), expectedValue, actualValue, result);
            } else {
    
    
                result.missing(prefix, key);
            }
        }
    }

默认,会检查字段是否存在于 JSON Object,我们可以重载这人方法,直接移除忽略字段的检查。

import java.util.Set;
 
import org.json.JSONException;
import org.json.JSONObject;
import org.skyscreamer.jsonassert.Customization;
import org.skyscreamer.jsonassert.JSONCompareMode;
import org.skyscreamer.jsonassert.JSONCompareResult;
import org.skyscreamer.jsonassert.comparator.CustomComparator;
 
public class MyComparator extends CustomComparator{
    
    
    private final Set<String> attributesToIgnore;
 
    public MyComparator(JSONCompareMode mode, Set<String> attributesToIgnore, Customization... customizations) {
    
    
        super(mode, customizations);
        this.attributesToIgnore = attributesToIgnore;
    }
 
    @Override
    protected void checkJsonObjectKeysExpectedInActual(String prefix, JSONObject expected, JSONObject actual, JSONCompareResult result) throws JSONException {
    
    
        //Remove ignored keys from json object
    	attributesToIgnore.forEach(attribute -> expected.remove(attribute));
        super.checkJsonObjectKeysExpectedInActual(prefix, expected, actual, result);
    }
}
import java.util.Arrays;
import java.util.HashSet;
 
import org.json.JSONException;
import org.skyscreamer.jsonassert.Customization;
import org.skyscreamer.jsonassert.JSONAssert;
import org.skyscreamer.jsonassert.JSONCompareMode;
import org.skyscreamer.jsonassert.comparator.JSONComparator;
 
public class IgnoreFieldsUsingMyComparator {
    
    
	
	public static void main(String[] args) throws JSONException {
    
    
		
		String s1 = "{\r\n" + 
				"  \"id\": 1,\r\n" + 
				"  \"first_name\": \"Amod\",\r\n" + 
				"  \"last_name\": \"Mahajan\",\r\n" + 
				"  \"married\": false,\r\n" + 
				"  \"salary\": 123.45\r\n" + 
				"}";
		String s2 = "{\r\n" + 
				"  \"id\": 1,\r\n" + 
				"  \"first_name\": \"Amod\",\r\n" + 
				"  \"last_name\": \"Mahajan\",\r\n" + 
				"  \"married\": false\r\n" + 
				"}";
		
		JSONComparator com = new MyComparator(JSONCompareMode.LENIENT,
				// Pass attributes to ignore
				new HashSet<String>(Arrays.asList("salary")),
				new Customization("firstName", (o1, o2) -> true),
				new Customization("age", (o1, o2) -> true));
		
		JSONAssert.assertEquals(s1, s2,com);
	}
 
}

这次比较就会 PASS了,但是这种方式不适合嵌套的 JSON Object 或 Arrays。需要重载更多方法去解决 JSON Object 或 Arrays 的问题。

猜你喜欢

转载自blog.csdn.net/wumingxiaoyao/article/details/120624148