Update for JSONArray.putAll methods

* Adds a copy constructor for JSONArray
* Updates the JSONArray.addAll(Object) method to be more lenient
* Adds support for JSONArray.putAll of generic Iterables
* Adds support for JSONArray.putAll of another JSONArray
This commit is contained in:
John J. Aylward 2020-07-27 11:39:55 -04:00
parent 6351fa63aa
commit f37c2d67c5
3 changed files with 158 additions and 5 deletions

View File

@ -177,6 +177,35 @@ public class JSONArray implements Iterable<Object> {
}
}
/**
* Construct a JSONArray from an Iterable. This is a shallow copy.
*
* @param iter
* A Iterable collection.
*/
public JSONArray(Iterable<?> iter) {
this();
if (iter == null) {
return;
}
this.addAll(iter);
}
/**
* Construct a JSONArray from another JSONArray. This is a shallow copy.
*
* @param collection
* A Collection.
*/
public JSONArray(JSONArray array) {
if (array == null) {
this.myArrayList = new ArrayList<Object>();
} else {
this.myArrayList = new ArrayList<Object>(array.length());
this.addAll(array.myArrayList);
}
}
/**
* Construct a JSONArray from an array.
*
@ -191,6 +220,10 @@ public class JSONArray implements Iterable<Object> {
*/
public JSONArray(Object array) throws JSONException {
this();
if (!array.getClass().isArray()) {
throw new JSONException(
"JSONArray initial value should be a string or collection or array.");
}
this.addAll(array);
}
@ -210,6 +243,11 @@ public class JSONArray implements Iterable<Object> {
this.myArrayList = new ArrayList<Object>(initialCapacity);
}
@Override
protected Object clone() {
return new JSONArray(this.myArrayList);
}
@Override
public Iterator<Object> iterator() {
return this.myArrayList.iterator();
@ -1165,7 +1203,7 @@ public class JSONArray implements Iterable<Object> {
}
/**
* Put or replace a collection's elements in the JSONArray.
* Put a collection's elements in to the JSONArray.
*
* @param collection
* A Collection.
@ -1177,7 +1215,31 @@ public class JSONArray implements Iterable<Object> {
}
/**
* Put or replace an array's elements in the JSONArray.
* Put an Iterable's elements in to the JSONArray.
*
* @param iter
* A Collection.
* @return this.
*/
public JSONArray putAll(Iterable<?> iter) {
this.addAll(iter);
return this;
}
/**
* Put a JSONArray's elements in to the JSONArray.
*
* @param array
* A JSONArray.
* @return this.
*/
public JSONArray putAll(JSONArray array) {
this.addAll(array.myArrayList);
return this;
}
/**
* Put an array's elements in to the JSONArray.
*
* @param array
* Array. If the parameter passed is null, or not an array, an
@ -1520,7 +1582,6 @@ public class JSONArray implements Iterable<Object> {
return this.myArrayList.isEmpty();
}
/**
* Add a collection's elements to the JSONArray.
*
@ -1534,6 +1595,18 @@ public class JSONArray implements Iterable<Object> {
}
}
/**
* Add an Iterable's elements to the JSONArray.
*
* @param iter
* An Iterable.
*/
private void addAll(Iterable<?> iter) {
for (Object o: iter){
this.myArrayList.add(JSONObject.wrap(o));
}
}
/**
* Add an array's elements to the JSONArray.
*
@ -1553,6 +1626,12 @@ public class JSONArray implements Iterable<Object> {
for (int i = 0; i < length; i += 1) {
this.put(JSONObject.wrap(Array.get(array, i)));
}
} else if (array instanceof JSONArray) {
this.addAll(((JSONArray)array).myArrayList);
} else if (array instanceof Collection) {
this.addAll((Collection<?>)array);
} else if (array instanceof Iterable) {
this.addAll((Iterable<?>)array);
} else {
throw new JSONException(
"JSONArray initial value should be a string or collection or array.");

View File

@ -979,9 +979,9 @@ public class JSONArrayTest {
JSONArray jsonArray = new JSONArray(str);
String expectedStr = str;
StringWriter stringWriter = new StringWriter();
try {
jsonArray.write(stringWriter);
String actualStr = stringWriter.toString();
try {
JSONArray finalArray = new JSONArray(actualStr);
Util.compareActualVsExpectedJsonArrays(jsonArray, finalArray);
assertTrue("write() expected " + expectedStr +
@ -1187,4 +1187,71 @@ public class JSONArrayTest {
e.getMessage());
}
}
/**
* Verifies that the object constructor can properly handle any supported collection object.
*/
@Test
@SuppressWarnings({ "unchecked", "boxing" })
public void testObjectConstructor() {
// should copy the array
Object o = new Object[] {2, "test2", true};
JSONArray a = new JSONArray(o);
assertNotNull("Should not error", a);
assertEquals("length", 3, a.length());
// should NOT copy the collection
// this is required for backwards compatibility
o = new ArrayList<Object>();
((Collection<Object>)o).add(1);
((Collection<Object>)o).add("test");
((Collection<Object>)o).add(false);
try {
a = new JSONArray(o);
assertNull("Should error", a);
} catch (JSONException ex) {
}
// should NOT copy the JSONArray
// this is required for backwards compatibility
o = a;
try {
a = new JSONArray(o);
assertNull("Should error", a);
} catch (JSONException ex) {
}
}
/**
* Verifies that the JSONArray constructor properly copies the original.
*/
@Test
public void testJSONArrayConstructor() {
// should copy the array
JSONArray a1 = new JSONArray("[2, \"test2\", true]");
JSONArray a2 = new JSONArray(a1);
assertNotNull("Should not error", a2);
assertEquals("length", a1.length(), a2.length());
for(int i = 0; i < a1.length(); i++) {
assertEquals("index " + i + " are equal", a1.get(i), a2.get(i));
}
}
/**
* Verifies that the object constructor can properly handle any supported collection object.
*/
@Test
public void testJSONArrayPutAll() {
// should copy the array
JSONArray a1 = new JSONArray("[2, \"test2\", true]");
JSONArray a2 = new JSONArray();
a2.putAll(a1);
assertNotNull("Should not error", a2);
assertEquals("length", a1.length(), a2.length());
for(int i = 0; i < a1.length(); i++) {
assertEquals("index " + i + " are equal", a1.get(i), a2.get(i));
}
}
}

View File

@ -3201,4 +3201,11 @@ public class JSONObjectTest {
fail("Expected an exception");
}
@Test
public void testIssue548ObjectWithEmptyJsonArray() {
JSONObject jsonObject = new JSONObject("{\"empty_json_array\": []}");
assertTrue("missing expected key 'empty_json_array'", jsonObject.has("empty_json_array"));
assertNotNull("'empty_json_array' should be an array", jsonObject.getJSONArray("empty_json_array"));
assertEquals("'empty_json_array' should have a length of 0", 0, jsonObject.getJSONArray("empty_json_array").length());
}
}