[SoapUI] 比较JSON Response
比较两个JSON, ID是数字时,处理成统一的格式:只保留小数点后5位
package direct; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.skyscreamer.jsonassert.JSONCompareMode; import org.skyscreamer.jsonassert.JSONCompareResult; import org.skyscreamer.jsonassert.comparator.DefaultComparator; import org.skyscreamer.jsonassert.JSONCompare; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.HashMap; import java.util.Map; import static org.skyscreamer.jsonassert.comparator.JSONCompareUtil.*; /** * Created by jenny zhang on 2017/9/19. */ public class LooseyJSONComparator extends DefaultComparator { private int scale; String extraInfo; def log; public LooseyJSONComparator(JSONCompareMode mode, int scale,String extraInfo,def log) { super(mode); this.scale = scale; this.extraInfo = extraInfo; this.log = log; } public static void assertEquals( String expected, String actual, int scale, String extraInfo, def log) throws JSONException { JSONCompareResult result = JSONCompare.compareJSON(expected, actual, new LooseyJSONComparator(JSONCompareMode.NON_EXTENSIBLE,scale,extraInfo,log)); if (result.failed()) { def failMessage = result.getMessage(); throw new AssertionError(extraInfo + failMessage); } else{ log.info "pass"; } } @Override protected void compareJSONArrayOfJsonObjects(String key, JSONArray expected, JSONArray actual, JSONCompareResult result) throws JSONException { String uniqueKey = findUniqueKey(expected); if (uniqueKey == null || !isUsableAsUniqueKey(uniqueKey, actual)) { // An expensive last resort recursivelyCompareJSONArray(key, expected, actual, result); return; } Map<Object, JSONObject> expectedValueMap = arrayOfJsonObjectToMap(expected, uniqueKey, log); Map<Object, JSONObject> actualValueMap = arrayOfJsonObjectToMap(actual, uniqueKey, log); for (Object id : expectedValueMap.keySet()) { if (!actualValueMap.containsKey(id)) { result.missing(formatUniqueKey(key, uniqueKey, expectedValueMap.get(id).get(uniqueKey)), expectedValueMap.get(id)); continue; } JSONObject expectedValue = expectedValueMap.get(id); JSONObject actualValue = actualValueMap.get(id); compareValues(formatUniqueKey(key, uniqueKey, id), expectedValue, actualValue, result); } for (Object id : actualValueMap.keySet()) { if (!expectedValueMap.containsKey(id)) { result.unexpected(formatUniqueKey(key, uniqueKey, actualValueMap.get(id).get(uniqueKey)), actualValueMap.get(id)); } } } private String getCompareValue(String value) { try{ return new BigDecimal(value).setScale(scale, RoundingMode.HALF_UP).toString(); } catch (NumberFormatException e) { return value; //value may = NaN, in this case, return value directly. } } private boolean isNumeric(Object value) { try { Double.parseDouble(value.toString()); return true; } catch (NumberFormatException e) { return false; } } public Map<Object, JSONObject> arrayOfJsonObjectToMap(JSONArray array, String uniqueKey,def log) throws JSONException { Map<Object, JSONObject> valueMap = new HashMap<Object, JSONObject>(); for (int i = 0; i < array.length(); ++i) { JSONObject jsonObject = (JSONObject) array.get(i); Object id = jsonObject.get(uniqueKey); id = isNumeric(id) ? getCompareValue(id.toString()) : id; valueMap.put(id, jsonObject); } return valueMap; } @Override public void compareValues(String prefix, Object expectedValue, Object actualValue, JSONCompareResult result) throws JSONException { if (areLeaf(expectedValue, actualValue)) { if (isNumeric(expectedValue) && isNumeric(actualValue)) { if (getCompareValue(expectedValue.toString()).equals(getCompareValue(actualValue.toString()))) { result.passed(); } else { result.fail(prefix, expectedValue, actualValue); } return; } } super.compareValues(prefix, expectedValue, actualValue, result); } private boolean areLeaf(Object expectedValue, Object actualValue) { boolean isLeafExpectedValue = !(expectedValue instanceof JSONArray)&&!(expectedValue instanceof JSONObject); boolean isLeafActualValue = !(actualValue instanceof JSONArray)&&!(actualValue instanceof JSONObject); return isLeafExpectedValue&&isLeafActualValue; } }