Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CS304 Fix issue#129 #143

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 121 additions & 0 deletions src/main/java/org/skyscreamer/jsonassert/JSONAssert.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.json.JSONException;
import org.json.JSONObject;
import org.skyscreamer.jsonassert.comparator.JSONComparator;
import java.util.ArrayList;

/**
* <p>A set of assertion methods useful for writing tests methods that return JSON.</p>
Expand Down Expand Up @@ -833,4 +834,124 @@ private static String getCombinedMessage(String message1, String message2) {
}
return combinedMessage;
}

//CS304 issue link: https://github.com/skyscreamer/JSONassert/issues/129

/**
* Asserts that the JSONString provided match the expected JSONString.
* If it isn't it throws an {@link AssertionError}
*
* @param expected Expected JSON String
* @param actual JSON String to compare
* @param ignoreList The list of field name (in String) wanted to ignore
* @param strict Defines comparison behavior
* @throws JSONException JSON parsing error
*/
public static void assertEqualsWithIgnore(String expected, String actual, ArrayList<String> ignoreList, boolean strict) throws JSONException {
JSONCompareResult result = JSONCompare.compareJSONWithIgnore(expected, actual, ignoreList,
strict?JSONCompareMode.STRICT:JSONCompareMode.LENIENT);
if (result.failed()){
throw new AssertionError(result.getMessage());
}
}

//CS304 issue link: https://github.com/skyscreamer/JSONassert/issues/129

/**
* Asserts that the JSONObject provided match the expected JSONObject.
* If it isn't it throws an {@link AssertionError}
*
* @param expected Expected JSON Object
* @param actual JSON Object to compare
* @param ignoreList The list of field name (in String) wanted to ignore
* @param strict Defines comparison behavior
* @throws JSONException JSON parsing error
*/
public static void assertEqualsWithIgnore(JSONObject expected, JSONObject actual, ArrayList<String> ignoreList, boolean strict) throws JSONException{
JSONCompareResult result = JSONCompare.compareJSONWithIgnore(expected, actual, ignoreList,
strict?JSONCompareMode.STRICT:JSONCompareMode.LENIENT);
if (result.failed()){
throw new AssertionError(result.getMessage());
}
}

//CS304 issue link: https://github.com/skyscreamer/JSONassert/issues/129

/**
* Asserts that the JSONArray provided match the expected JSONArray.
* If it isn't it throws an {@link AssertionError}
*
* @param expected Expected JSON Array
* @param actual JSON Array to compare
* @param ignoreList The list of field name (in String) wanted to ignore
* @param strict Defines comparison behavior
* @throws JSONException JSON parsing error
*/
public static void assertEqualsWithIgnore(JSONArray expected, JSONArray actual, ArrayList<String> ignoreList, boolean strict) throws JSONException{
JSONCompareResult result = JSONCompare.compareJSONWithIgnore(expected, actual, ignoreList,
strict?JSONCompareMode.STRICT:JSONCompareMode.LENIENT);
if (result.failed()){
throw new AssertionError(result.getMessage());
}
}

//CS304 issue link: https://github.com/skyscreamer/JSONassert/issues/129

/**
* Asserts that the JSONString provided does not match the expected JSONString.
* If it is it throws an {@link AssertionError}
*
* @param expected Expected JSON String
* @param actual JSON String to compare
* @param ignoreList The list of field name (in String) wanted to ignore
* @param strict Defines comparison behavior
* @throws JSONException JSON parsing error
*/
public static void assertNotEqualsWithIgnore(String expected, String actual, ArrayList<String> ignoreList, boolean strict) throws JSONException{
JSONCompareResult result = JSONCompare.compareJSONWithIgnore(expected, actual, ignoreList,
strict?JSONCompareMode.STRICT:JSONCompareMode.LENIENT);
if (result.passed()){
throw new AssertionError("Two JSONs are equal!");
}
}

//CS304 issue link: https://github.com/skyscreamer/JSONassert/issues/129

/**
* Asserts that the JSONObject provided does not match the expected JSONObject.
* If it is it throws an {@link AssertionError}
*
* @param expected Expected JSON Object
* @param actual JSON Object to compare
* @param ignoreList The list of field name (in String) wanted to ignore
* @param strict Defines comparison behavior
* @throws JSONException JSON parsing error
*/
public static void assertNotEqualsWithIgnore(JSONObject expected, JSONObject actual, ArrayList<String> ignoreList, boolean strict) throws JSONException{
JSONCompareResult result = JSONCompare.compareJSONWithIgnore(expected, actual, ignoreList,
strict?JSONCompareMode.STRICT:JSONCompareMode.LENIENT);
if (result.passed()){
throw new AssertionError("Two JSONs are equal!");
}
}

//CS304 issue link: https://github.com/skyscreamer/JSONassert/issues/129

/**
* Asserts that the JSONArray provided does not match the expected JSONArray.
* If it is it throws an {@link AssertionError}
*
* @param expected Expected JSON Array
* @param actual JSON Array to compare
* @param ignoreList The list of field name (in String) wanted to ignore
* @param strict Defines comparison behavior
* @throws JSONException JSON parsing error
*/
public static void assertNotEqualsWithIgnore(JSONArray expected, JSONArray actual, ArrayList<String> ignoreList, boolean strict) throws JSONException{
JSONCompareResult result = JSONCompare.compareJSONWithIgnore(expected, actual, ignoreList,
strict?JSONCompareMode.STRICT:JSONCompareMode.LENIENT);
if (result.passed()){
throw new AssertionError("Two JSONs are equal!");
}
}
}
195 changes: 195 additions & 0 deletions src/main/java/org/skyscreamer/jsonassert/JSONCompare.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
import org.json.JSONString;
import org.skyscreamer.jsonassert.comparator.DefaultComparator;
import org.skyscreamer.jsonassert.comparator.JSONComparator;
import java.util.ArrayList;
import java.util.Iterator;

/**
* Provides API to compare two JSON entities. This is the backend to {@link JSONAssert}, but it can
Expand Down Expand Up @@ -124,6 +126,199 @@ public static JSONCompareResult compareJSON(String expectedStr, String actualStr
throws JSONException {
return compareJSON(expectedStr, actualStr, getComparatorForMode(mode));
}

//CS304 Issue link: https://github.com/skyscreamer/JSONassert/issues/129

/**
* The recursive method to check if the JSONObject has the target field.
* If not, return false; if have, remove the target field and return true.
*
* @param target The target field that we want to check
* @param obj The target JSONObject that we want to check and remove the target field
* @return A boolean value indicates whether the target field is found
* @throws JSONException JSON parsing error
*/
protected static boolean checkAndRemove(String target, JSONObject obj) throws JSONException {
boolean result = false;
Iterator<String> iterator = obj.keys();
while (iterator.hasNext()){
String key = iterator.next();
Object value = obj.get(key);
if (value instanceof JSONObject){
result = checkAndRemove(target, (JSONObject)value);
}else if (value instanceof JSONArray){
result = false;
JSONArray valueArray = (JSONArray) value;
for (int i = 0; i < valueArray.length(); i++){
if (valueArray.get(i) instanceof JSONObject) {
result = result | checkAndRemove(target, ((JSONArray) value).getJSONObject(i));
}else if (valueArray.get(i) instanceof JSONArray){
result = result | checkAndRemove(target, (JSONArray) ((JSONArray) value).get(i));
}
}
}
}
if (obj.has(target)){
result = true;
obj.remove(target);
}
return result;
}

//CS304 Issue link: https://github.com/skyscreamer/JSONassert/issues/129

/**
* The recursive method to check if a JSON Array contains target field.
* Add this method to avoid recursively constructed JSON Array
*
* @param target The target field that we want to check
* @param obj he target JSONArray that we want to check and remove the target field
* @return A boolean value indicates whether the JSONArray contains the target field.
* @throws JSONException JSON parsing error
*/
protected static boolean checkAndRemove(String target, JSONArray obj) throws JSONException {
boolean result = false;
for (int i = 0; i < obj.length(); i++){
if (obj.get(i) instanceof JSONArray){
result = result | checkAndRemove(target, (JSONArray) obj.get(i));
}else if (obj.get(i) instanceof JSONObject){
result = result | checkAndRemove(target, (JSONObject) obj.get(i));
}
}
return result;
}

//CS304 Issue link: https://github.com/skyscreamer/JSONassert/issues/129

/**
* Provide a ignore list, compare the two JSONObject ignoring these fields.
* If the ignore list is empty, which means you don't want to ignore anything, then, please use other method without ignore.
*
* @param expect Expected JSONObject
* @param actual JSONObject to compare
* @param ignoreList The list of field name (in String) wanted to ignore
* @param mode Defines comparison behavior
* @return result of the comparison
* @throws JSONException JSON parsing error
*/
public static JSONCompareResult compareJSONWithIgnore(JSONObject expect, JSONObject actual, ArrayList<String> ignoreList, JSONCompareMode mode) throws JSONException {
if (ignoreList.size() == 0){
JSONCompareResult result = new JSONCompareResult();
result.fail("Please use other mode if don't want to ignore any field");
return result;
}
ArrayList<String> errorFields = new ArrayList<String>();
for (String toIgnore : ignoreList) {
boolean have = checkAndRemove(toIgnore, expect) | checkAndRemove(toIgnore, actual);
if (!have){
errorFields.add(toIgnore);
}
}
if (errorFields.size() == 0){
return compareJSON(expect, actual, mode);
}else{
JSONCompareResult result = new JSONCompareResult();
StringBuilder message = new StringBuilder("Following ignore field(s) not found:\n");
for (String field: errorFields){
message.append(field);
message.append("\n");
}
result.fail(message.toString());
return result;
}
}

//CS304 Issue link: https://github.com/skyscreamer/JSONassert/issues/129

/**
* Provide a ignore list, compare the two JSONArray ignoring these fields.
* If the ignore list is empty, which means you don't want to ignore anything, then, please use other method without ignore.
* @param expect Expected JSONArray
* @param actual JSONArray to compare
* @param ignoreList The list of field name (in String) wanted to ignore
* @param mode Defines comparison behavior
* @return result of the comparison
* @throws JSONException JSON parsing error
*/
public static JSONCompareResult compareJSONWithIgnore(JSONArray expect, JSONArray actual, ArrayList<String> ignoreList, JSONCompareMode mode) throws JSONException{
if (ignoreList.size() == 0){
JSONCompareResult result = new JSONCompareResult();
result.fail("Please use other mode if don't want to ignore any field");
return result;
}
ArrayList<String> errorFields = new ArrayList<String>();
for (String toIgnore: ignoreList){
boolean have = false;
for (int i = 0; i < expect.length(); i++){
if (expect.get(i) instanceof JSONObject) {
JSONObject element = expect.getJSONObject(i);
have = checkAndRemove(toIgnore, element) | have;
}else if (expect.get(i) instanceof JSONArray){
JSONArray element = (JSONArray) expect.get(i);
have = checkAndRemove(toIgnore, element);
}

}
for (int i = 0; i < actual.length(); i++){
if (actual.get(i) instanceof JSONObject) {
JSONObject element = actual.getJSONObject(i);
have = checkAndRemove(toIgnore, element) | have;
}else if (actual.get(i) instanceof JSONArray){
JSONArray element = (JSONArray) actual.get(i);
have = checkAndRemove(toIgnore, element) | have;
}
}
if (!have){
errorFields.add(toIgnore);
}
}
if (errorFields.size() == 0){
return compareJSON(expect, actual, mode);
}else{
JSONCompareResult result = new JSONCompareResult();
StringBuilder message = new StringBuilder("Following ignore field(s) not found:\n");
for (String field: errorFields){
message.append(field);
message.append("\n");
}
result.fail(message.toString());
return result;
}
}

//CS304 Issue link: https://github.com/skyscreamer/JSONassert/issues/129

/**
* Compare JSON String provided to the expected JSON string and returns the results of the comparison.
*
* @param expectedStr Expected JSON String
* @param actualStr JSON String to compare
* @param ignoreList The list of field name (in String) wanted to ignore
* @param mode Defines comparison behavior
* @return result of the comparison
* @throws JSONException JSON parsing error
*/
public static JSONCompareResult compareJSONWithIgnore(String expectedStr, String actualStr, ArrayList<String> ignoreList, JSONCompareMode mode) throws JSONException {
if (ignoreList.size() == 0){
JSONCompareResult result = new JSONCompareResult();
result.fail("Please use other mode if don't want to ignore any field");
return result;
}
Object _expect = JSONParser.parseJSON(expectedStr);
Object _actual = JSONParser.parseJSON(actualStr);
if ((_expect instanceof JSONObject) && (_actual instanceof JSONObject)){
return compareJSONWithIgnore((JSONObject)_expect, (JSONObject)_actual, ignoreList, mode);
}else if ((_expect instanceof JSONArray) && (_actual instanceof JSONArray)){
return compareJSONWithIgnore((JSONArray)_expect, (JSONArray)_actual, ignoreList, mode);
}else if ((_expect instanceof JSONString) && (_actual instanceof JSONString)){
return compareJSONWithIgnore(((JSONString)_expect).toJSONString(), ((JSONString)_actual).toJSONString(), ignoreList, mode);
}else if (_expect instanceof JSONObject) {
return new JSONCompareResult().fail("", _expect, _actual);
}
else {
return new JSONCompareResult().fail("", _expect, _actual);
}
}

/**
* Compares JSONObject provided to the expected JSONObject, and returns the results of the comparison.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,52 @@ public void compareValues(String prefix, Object expectedValue, Object actualValu
}
}

/**
* Generate error message for JSONArray comparision.<br>
*
* Solve problem mentioned in <a href="https://github.com/skyscreamer/JSONassert/issues/128">issue 128</a>
* @author Chengqi Xu
* @param prefix The prefix description given in compareJSONArray
* @param expected The expected length of the JSONArray
* @param actual The actual length of the JSONArray
* @return The description used as error message for JSONArray comparision
**/
// CS304 Issue link: https://github.com/skyscreamer/JSONassert/issues/128
public String getMessage(String prefix, int expected, int actual){
StringBuilder msgBuilder = new StringBuilder(prefix);
String description1 = " values but got ";
String description2 = "";
if (actual > 1) {
description2 = " values.";
}
else {
description2 = " value.";
}
if (expected <= 1) {
description1 = " value but got ";
}
msgBuilder.append("[]: Expected ");
msgBuilder.append(expected);
msgBuilder.append(description1);
msgBuilder.append(actual);
msgBuilder.append(description2);
return msgBuilder.toString();
}

/**
*
* @param prefix the path in the json where the comparison happens
* @param expected the expected JSON array
* @param actual the actual JSON array
* @param result stores the actual state of the comparison result
* @throws JSONException Used to indicate the error
*/
// CS304 Issue link: https://github.com/skyscreamer/JSONassert/issues/128
@Override
public void compareJSONArray(String prefix, JSONArray expected, JSONArray actual, JSONCompareResult result)
throws JSONException {
if (expected.length() != actual.length()) {
result.fail(prefix + "[]: Expected " + expected.length() + " values but got " + actual.length());
result.fail(getMessage(prefix,expected.length(), actual.length()));
return;
} else if (expected.length() == 0) {
return; // Nothing to compare
Expand Down
Loading