net.pwall.json.JSONArray Maven / Gradle / Ivy
/*
* @(#) JSONArray.java
*
* jsonutil JSON Utility Library
* Copyright (c) 2014, 2015 Peter Wall
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package net.pwall.json;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/**
* A JSON array.
*
* @author Peter Wall
*/
public class JSONArray extends ArrayList implements JSONComposite {
private static final long serialVersionUID = -6963671812529472759L;
/**
* Construct an empty JSON array.
*/
public JSONArray() {
}
/**
* Construct a JSON array by copying another JSON array.
*
* @param array the source {@code JSONArray}
* @throws NullPointerException if the collection is {@code null}
*/
public JSONArray(JSONValue[] array) {
for (JSONValue item : requireNonNull(array))
add(item);
}
/**
* Construct a JSON array from a {@link Collection} of JSON values.
*
* @param collection the source {@link Collection}
* @throws NullPointerException if the collection is {@code null}
*/
public JSONArray(Collection collection) {
super(collection);
}
/**
* Add a {@link JSONString} to the JSON array representing the supplied {@link CharSequence}
* ({@link String}, {@link StringBuilder} etc.).
*
* @param cs the {@link CharSequence}
* @return {@code this} (for chaining)
* @throws NullPointerException if the value is {@code null}
*/
public JSONArray addValue(CharSequence cs) {
add(new JSONString(cs));
return this;
}
/**
* Add a {@link JSONInteger} to the JSON array representing the supplied {@code int}.
*
* @param value the value
* @return {@code this} (for chaining)
*/
public JSONArray addValue(int value) {
add(JSONInteger.valueOf(value));
return this;
}
/**
* Add a {@link JSONLong} to the JSON array representing the supplied {@code long}.
*
* @param value the value
* @return {@code this} (for chaining)
*/
public JSONArray addValue(long value) {
add(JSONLong.valueOf(value));
return this;
}
/**
* Add a {@link JSONFloat} to the JSON array representing the supplied {@code float}.
*
* @param value the value
* @return {@code this} (for chaining)
*/
public JSONArray addValue(float value) {
add(JSONFloat.valueOf(value));
return this;
}
/**
* Add a {@link JSONDouble} to the JSON array representing the supplied {@code double}.
*
* @param value the value
* @return {@code this} (for chaining)
*/
public JSONArray addValue(double value) {
add(JSONDouble.valueOf(value));
return this;
}
/**
* Add a {@link JSONBoolean} to the JSON array representing the supplied {@code boolean}.
*
* @param value the value
* @return {@code this} (for chaining)
*/
public JSONArray addValue(boolean value) {
add(JSONBoolean.valueOf(value));
return this;
}
/**
* Add a {@link JSONBoolean} to the JSON array representing the supplied {@link Boolean}.
*
* @param value the value
* @return {@code this} (for chaining)
* @throws NullPointerException if the value is {@code null}
*/
public JSONArray addValue(Boolean value) {
add(JSONBoolean.valueOf(requireNonNull(value).booleanValue()));
return this;
}
public JSONArray addValues(Collection collection) {
for (CharSequence value : collection)
addValue(value);
return this;
}
public JSONArray addValues(T[] array) {
for (int i = 0, n = array.length; i < n; i++)
addValue(array[i]);
return this;
}
public JSONArray addValues(int[] array) {
for (int i = 0, n = array.length; i < n; i++)
addValue(array[i]);
return this;
}
public JSONArray addValues(long[] array) {
for (int i = 0, n = array.length; i < n; i++)
addValue(array[i]);
return this;
}
public JSONArray addValues(float[] array) {
for (int i = 0, n = array.length; i < n; i++)
addValue(array[i]);
return this;
}
public JSONArray addValues(double[] array) {
for (int i = 0, n = array.length; i < n; i++)
addValue(array[i]);
return this;
}
/**
* Add a {@code null} value to the JSON array.
*
* @return {@code this} (for chaining)
*/
public JSONArray addNull() {
add(null);
return this;
}
/**
* Add a {@link JSONValue} to the {@code JSONArray}. This method duplicates the
* {@link ArrayList#add(Object) add(JSONValue)} method inherited from the {@link ArrayList}
* class, but it returns {@code this} to allow for chaining.
*
* @param json the {@link JSONValue}
* @return {@code this} (for chaining)
*/
public JSONArray addJSON(JSONValue json) {
add(json);
return this;
}
/**
* Get a {@link String} value from the array. If the array entry is {@code null} return
* {@code null}.
*
* @param index the index of the value
* @return the value
* @throws JSONException if the array entry is not a {@link JSONString}
*/
public String getString(int index) {
return JSON.getString(get(index));
}
/**
* Get an {@code int} value from the array. If the array entry is {@code null} return 0.
*
* @param index the index of the value
* @return the value
* @throws JSONException if the array entry is not a {@link Number}
*/
public int getInt(int index) {
return JSON.getInt(get(index));
}
/**
* Get a {@code long} value from the array. If the array entry is {@code null} return 0.
*
* @param index the index of the value
* @return the value
* @throws JSONException if the array entry is not a {@link Number}
*/
public long getLong(int index) {
return JSON.getLong(get(index));
}
/**
* Get a {@code float} value from the array. If the array entry is {@code null} return 0.
*
* @param index the index of the value
* @return the value
* @throws JSONException if the array entry is not a {@link Number}
*/
public float getFloat(int index) {
return JSON.getFloat(get(index));
}
/**
* Get a {@code double} value from the array. If the array entry is {@code null} return 0.
*
* @param index the index of the value
* @return the value
* @throws JSONException if the array entry is not a {@link Number}
*/
public double getDouble(int index) {
return JSON.getDouble(get(index));
}
/**
* Get a {@code boolean} value from the array. If the array entry is {@code null} return
* {@code false}.
*
* @param index the index of the value
* @return the value
* @throws JSONException if the array entry is not a {@link JSONBoolean}
*/
public boolean getBoolean(int index) {
return JSON.getBoolean(get(index));
}
/**
* Get a {@link JSONArray} value from the array. If the array entry is {@code null} return
* {@code null}.
*
* @param index the index of the value
* @return the value
* @throws JSONException if the array entry is not a {@link JSONArray}
*/
public JSONArray getArray(int index) {
return JSON.getArray(get(index));
}
/**
* Get a {@link JSONObject} value from the array. If the array entry is {@code null} return
* {@code null}.
*
* @param index the index of the value
* @return the value
* @throws JSONException if the array entry is not a {@link JSONArray}
*/
public JSONObject getObject(int index) {
return JSON.getObject(get(index));
}
/**
* Get an {@link Iterable} of {@link String} from this array. Supports the idiom:
*
* for (String item : jsonArray.strings()) {
* // process each item of the array
* }
*
* The resulting {@link Iterator} will throw a {@link JSONException} if any item in the
* array is not a {@link String} or {@code null}.
*
* @return an {@link Iterable} of {@link String}
*/
public Iterable strings() {
return new Iterable() {
@Override
public Iterator iterator() {
return new StringIterator();
}
};
}
/**
* Get an {@link Iterable} of {@link Integer} from this array. Supports the idiom:
*
* for (Integer item : jsonArray.ints()) {
* // process each item of the array
* }
*
* The resulting {@link Iterator} will throw a {@link JSONException} if any item in the
* array is not a {@link Integer} or {@code null}.
*
* @return an {@link Iterable} of {@link Integer}
*/
public Iterable ints() {
return new Iterable() {
@Override
public Iterator iterator() {
return new IntegerIterator();
}
};
}
/**
* Get an {@link Iterable} of {@link Long} from this array. Supports the idiom:
*
* for (Long item : jsonArray.longs()) {
* // process each item of the array
* }
*
* The resulting {@link Iterator} will throw a {@link JSONException} if any item in the
* array is not a {@link Long} or {@code null}.
*
* @return an {@link Iterable} of {@link Long}
*/
public Iterable longs() {
return new Iterable() {
@Override
public Iterator iterator() {
return new LongIterator();
}
};
}
/**
* Get an {@link Iterable} of {@link Double} from this array. Supports the idiom:
*
* for (Double item : jsonArray.doubles()) {
* // process each item of the array
* }
*
* The resulting {@link Iterator} will throw a {@link JSONException} if any item in the
* array is not a {@link Double} or {@code null}.
*
* @return an {@link Iterable} of {@link Double}
*/
public Iterable doubles() {
return new Iterable() {
@Override
public Iterator iterator() {
return new DoubleIterator();
}
};
}
/**
* Get an {@link Iterable} of {@link Float} from this array. Supports the idiom:
*
* for (Float item : jsonArray.floats()) {
* // process each item of the array
* }
*
* The resulting {@link Iterator} will throw a {@link JSONException} if any item in the
* array is not a {@link Float} or {@code null}.
*
* @return an {@link Iterable} of {@link Float}
*/
public Iterable floats() {
return new Iterable() {
@Override
public Iterator iterator() {
return new FloatIterator();
}
};
}
/**
* Get an {@link Iterable} of {@link Boolean} from this array. Supports the idiom:
*
* for (Boolean item : jsonArray.booleans()) {
* // process each item of the array
* }
*
* The resulting {@link Iterator} will throw a {@link JSONException} if any item in the
* array is not a {@link Boolean} or {@code null}.
*
* @return an {@link Iterable} of {@link Boolean}
*/
public Iterable booleans() {
return new Iterable() {
@Override
public Iterator iterator() {
return new BooleanIterator();
}
};
}
/**
* Get an {@link Iterable} of {@link JSONArray} from this array. Supports the idiom:
*
* for (JSONArray item : jsonArray.arrays()) {
* // process each item of the array
* }
*
* The resulting {@link Iterator} will throw a {@link JSONException} if any item in the
* array is not a {@link JSONArray} or {@code null}.
*
* @return an {@link Iterable} of {@link JSONArray}
*/
public Iterable arrays() {
return new Iterable() {
@Override
public Iterator iterator() {
return new ArrayIterator();
}
};
}
/**
* Get an {@link Iterable} of {@link JSONObject} from this array. Supports the idiom:
*
* for (JSONObject item : jsonArray.objects()) {
* // process each item of the array
* }
*
* The resulting {@link Iterator} will throw a {@link JSONException} if any item in the
* array is not a {@link JSONObject} or {@code null}.
*
* @return an {@link Iterable} of {@link JSONObject}
*/
public Iterable objects() {
return new Iterable() {
@Override
public Iterator iterator() {
return new ObjectIterator();
}
};
}
/**
* Create the external representation for this JSON array.
*
* @return the JSON representation for this array
* @see JSONValue#toJSON()
*/
@Override
public String toJSON() {
int estimate = size() * 20;
StringBuilder sb = new StringBuilder(estimate);
try {
appendJSON(sb);
}
catch (IOException e) {
// can't happen - StringBuilder does not throw IOException
}
return sb.toString();
}
/**
* Append the external representation for this JSON array to a given {@link Appendable}.
*
* @param a the {@link Appendable}
* @throws IOException if thrown by the {@link Appendable}
* @see JSONValue#appendJSON(Appendable)
*/
@Override
public void appendJSON(Appendable a) throws IOException {
a.append('[');
if (size() > 0) {
int i = 0;
for (;;) {
JSON.appendJSON(a, get(i++));
if (i >= size())
break;
a.append(',');
}
}
a.append(']');
}
/**
* Test whether the composite is "simple", i.e. it contains only non-composite values (to
* assist with formatting).
*
* @return {@code true} if the composite is simple
* @see JSONComposite#isSimple()
*/
@Override
public boolean isSimple() {
for (int i = 0; i < size(); i++)
if (get(i) instanceof JSONComposite)
return false;
return true;
}
/**
* Return a string representation of the JSON array. This is the same as the JSON format.
*
* @return the JSON string
*/
@Override
public String toString() {
return toJSON();
}
/**
* Compare two JSON arrays for equality.
*
* @param other the other JSON array
* @return {@code true} if the other object is a JSON array and the contents are equal
*/
@Override
public boolean equals(Object other) {
return other == this || other instanceof JSONArray && super.equals(other);
}
/**
* Convenience method to create a {@code JSONArray}. Supports the idiom:
*
* JSONArray arr = JSONArray.create().addValue(0).addValue(1).addValue(2);
*
*
* @return the new {@code JSONArray}
*/
public static JSONArray create() {
return new JSONArray();
}
private static T requireNonNull(T obj) {
if (obj == null)
throw new NullPointerException();
return obj;
}
public abstract class BaseIterator implements Iterator {
protected Iterator iterator = iterator();
@Override
public boolean hasNext() {
return iterator.hasNext();
}
@Override
public void remove() {
iterator.remove();
}
}
public class StringIterator extends BaseIterator {
@Override
public String next() {
return JSON.getString(iterator.next());
}
}
public class IntegerIterator extends BaseIterator {
@Override
public Integer next() {
JSONValue value = iterator.next();
if (value == null)
return null;
if (!(value instanceof Number))
throw new JSONException(JSON.NOT_A_NUMBER);
return ((Number)value).intValue();
}
}
public class LongIterator extends BaseIterator {
@Override
public Long next() {
JSONValue value = iterator.next();
if (value == null)
return null;
if (!(value instanceof Number))
throw new JSONException(JSON.NOT_A_NUMBER);
return ((Number)value).longValue();
}
}
public class DoubleIterator extends BaseIterator {
@Override
public Double next() {
JSONValue value = iterator.next();
if (value == null)
return null;
if (!(value instanceof Number))
throw new JSONException(JSON.NOT_A_NUMBER);
return ((Number)value).doubleValue();
}
}
public class FloatIterator extends BaseIterator {
@Override
public Float next() {
JSONValue value = iterator.next();
if (value == null)
return null;
if (!(value instanceof Number))
throw new JSONException(JSON.NOT_A_NUMBER);
return ((Number)value).floatValue();
}
}
public class BooleanIterator extends BaseIterator {
@Override
public Boolean next() {
JSONValue value = iterator.next();
if (value == null)
return null;
if (!(value instanceof JSONBoolean))
throw new JSONException(JSON.NOT_A_BOOLEAN);
return ((JSONBoolean)value).booleanValue();
}
}
public class ArrayIterator extends BaseIterator {
@Override
public JSONArray next() {
return JSON.getArray(iterator.next());
}
}
public class ObjectIterator extends BaseIterator {
@Override
public JSONObject next() {
return JSON.getObject(iterator.next());
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy