package com.xiaoleilu.hutool.json;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
/**
* JSON数组
* @author looly
*/
public class JSONArray extends JSONGetter<Integer> implements JSON, List<Object>{
/** 持有原始数据的List */
private final ArrayList<Object> rawArrayList;
//-------------------------------------------------------------------------------------------------------------------- Constructor start
/**
* 构造
*/
public JSONArray() {
this.rawArrayList = new ArrayList<Object>();
}
/**
* 使用 {@link JSONTokener} 做为参数构造
*
* @param x A {@link JSONTokener}
* @throws JSONException If there is a syntax error.
*/
public JSONArray(JSONTokener x) throws JSONException {
this();
if (x.nextClean() != '[') {
throw x.syntaxError("A JSONArray text must start with '['");
}
if (x.nextClean() != ']') {
x.back();
for (;;) {
if (x.nextClean() == ',') {
x.back();
this.rawArrayList.add(JSONNull.NULL);
} else {
x.back();
this.rawArrayList.add(x.nextValue());
}
switch (x.nextClean()) {
case ',':
if (x.nextClean() == ']') {
return;
}
x.back();
break;
case ']':
return;
default:
throw x.syntaxError("Expected a ',' or ']'");
}
}
}
}
/**
* 从String构造(JSONArray字符串)
*
* @param source JSON数组字符串
* @throws JSONException If there is a syntax error.
*/
public JSONArray(String source) throws JSONException {
this(new JSONTokener(source));
}
/**
* 从数组或{@link Collection}对象构造
*
* @throws JSONException 非数组或集合
*/
public JSONArray(Object arrayOrCollection) throws JSONException {
this();
if (arrayOrCollection.getClass().isArray()) {//数组
int length = Array.getLength(arrayOrCollection);
for (int i = 0; i < length; i += 1) {
this.put(JSONUtil.wrap(Array.get(arrayOrCollection, i)));
}
} else if(arrayOrCollection instanceof Iterable<?>){//Iterable
for (Object o : (Collection<?>)arrayOrCollection) {
this.add(o);
}
}else{
throw new JSONException("JSONArray initial value should be a string or collection or array.");
}
}
//-------------------------------------------------------------------------------------------------------------------- Constructor start
/**
* 值是否为<code>null</code>
*
* @param index 值所在序列
* @return true if the value at the index is null, or if there is no value.
*/
public boolean isNull(int index) {
return JSONNull.NULL.equals(this.getObj(index));
}
/**
*JSONArray转为以<code>separator</code>为分界符的字符串
*
* @param separator 分界符
* @return a string.
* @throws JSONException If the array contains an invalid number.
*/
public String join(String separator) throws JSONException {
int len = this.rawArrayList.size();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < len; i += 1) {
if (i > 0) {
sb.append(separator);
}
sb.append(InternalJSONUtil.valueToString(this.rawArrayList.get(i)));
}
return sb.toString();
}
@Override
public Object get(int index) {
return this.rawArrayList.get(index);
}
@Override
public Object getObj(Integer index, Object defaultValue) {
return (index < 0 || index >= this.size()) ? defaultValue : this.rawArrayList.get(index);
}
/**
* Append an object value. This increases the array's length by one.
* 加入元素,数组长度+1,等同于 {@link JSONArray#add(Object)}
*
* @param value 值,可以是: Boolean, Double, Integer, JSONArray, JSONObject, Long, or String, or the JSONNull.NULL。
* @return this.
*/
public JSONArray put(Object value) {
this.add(value);
return this;
}
/**
* 加入或者替换JSONArray中指定Index的值,如果index大于JSONArray的长度,将在指定index设置值,之前的位置填充JSONNull.Null
*
* @param index 位置
* @param value 值对象. 可以是以下类型: Boolean, Double, Integer, JSONArray, JSONObject, Long, String, or the JSONNull.NULL.
* @return this.
* @throws JSONException index < 0 或者非有限的数字
*/
public JSONArray put(int index, Object value) throws JSONException {
this.add(index, value);
return this;
}
/**
* 是否与其它对象相等,其它对象也必须是JSONArray,对象元素相等且元素顺序一致
*
* @param other The other JSONArray
* @return true if they are equal
*/
@Override
public boolean equals(Object other) {
if (!(other instanceof JSONArray)) {
return false;
}
int len = this.size();
if (len != ((JSONArray) other).size()) {
return false;
}
for (int i = 0; i < len; i += 1) {
Object valueThis = this.getObj(i);
Object valueOther = ((JSONArray) other).getObj(i);
if (valueThis instanceof JSONObject) {
if (!((JSONObject) valueThis).equals(valueOther)) {
return false;
}
} else if (valueThis instanceof JSONArray) {
if (!((JSONArray) valueThis).equals(valueOther)) {
return false;
}
} else if (!valueThis.equals(valueOther)) {
return false;
}
}
return true;
}
/**
* 根据给定名列表,与其位置对应的值组成JSONObject
*
* @param names 名列表,位置与JSONArray中的值位置对应
* @return A JSONObject,无名或值返回null
* @throws JSONException 如果任何一个名为null
*/
public JSONObject toJSONObject(JSONArray names) throws JSONException {
if (names == null || names.size() == 0 || this.size() == 0) {
return null;
}
JSONObject jo = new JSONObject();
for (int i = 0; i < names.size(); i += 1) {
jo.put(names.getStr(i), this.getObj(i));
}
return jo;
}
/**
* 转为JSON字符串,无缩进
*
* @return JSONArray字符串
*/
@Override
public String toString() {
try {
return this.toJSONString(0);
} catch (Exception e) {
return null;
}
}
/**
* 转为JSON字符串,指定缩进值
*
* @param indentFactor 缩进值,既缩进空格数
* @return JSON字符串
* @throws JSONException
*/
@Override
public String toJSONString(int indentFactor) throws JSONException {
StringWriter sw = new StringWriter();
synchronized (sw.getBuffer()) {
return this.write(sw, indentFactor, 0).toString();
}
}
@Override
public Writer write(Writer writer) throws JSONException {
return this.write(writer, 0, 0);
}
@Override
public Writer write(Writer writer, int indentFactor, int indent) throws JSONException {
try {
boolean commanate = false;
int length = this.size();
writer.write('[');
if (length == 1) {
InternalJSONUtil.writeValue(writer, this.rawArrayList.get(0), indentFactor, indent);
} else if (length != 0) {
final int newindent = indent + indentFactor;
for (int i = 0; i < length; i += 1) {
if (commanate) {
writer.write(',');
}
if (indentFactor > 0) {
writer.write('\n');
}
InternalJSONUtil.indent(writer, newindent);
InternalJSONUtil.writeValue(writer, this.rawArrayList.get(i), indentFactor, newindent);
commanate = true;
}
if (indentFactor > 0) {
writer.write('\n');
}
InternalJSONUtil.indent(writer, indent);
}
writer.write(']');
return writer;
} catch (IOException e) {
throw new JSONException(e);
}
}
@Override
public Iterator<Object> iterator() {
return rawArrayList.iterator();
}
@Override
public int size() {
return rawArrayList.size();
}
@Override
public boolean isEmpty() {
return rawArrayList.isEmpty();
}
@Override
public boolean contains(Object o) {
return rawArrayList.contains(o);
}
@Override
public Object[] toArray() {
return rawArrayList.toArray();
}
@Override
public <T> T[] toArray(T[] a) {
return rawArrayList.toArray(a);
}
@Override
public boolean add(Object e) {
return this.rawArrayList.add(JSONUtil.wrap(e));
}
@Override
public Object remove(int index) {
return index >= 0 && index < this.size() ? this.rawArrayList.remove(index) : null;
}
@Override
public boolean remove(Object o) {
return rawArrayList.remove(o);
}
@Override
public boolean containsAll(Collection<?> c) {
return rawArrayList.containsAll(c);
}
@Override
public boolean addAll(Collection<? extends Object> c) {
for (Object obj : c) {
this.add(obj);
}
return rawArrayList.addAll(c);
}
@Override
public boolean addAll(int index, Collection<? extends Object> c) {
return rawArrayList.addAll(index, c);
}
@Override
public boolean removeAll(Collection<?> c) {
return this.rawArrayList.removeAll(c);
}
@Override
public boolean retainAll(Collection<?> c) {
return this.rawArrayList.retainAll(c);
}
@Override
public void clear() {
this.rawArrayList.clear();
}
@Override
public Object set(int index, Object element) {
return this.rawArrayList.set(index, JSONUtil.wrap(element));
}
@Override
public void add(int index, Object element) {
if (index < 0) {
throw new JSONException("JSONArray[" + index + "] not found.");
}
if (index < this.size()) {
InternalJSONUtil.testValidity(element);
this.rawArrayList.set(index, JSONUtil.wrap(element));
} else {
while (index != this.size()) {
this.add(JSONNull.NULL);
}
this.put(element);
}
}
@Override
public int indexOf(Object o) {
return this.rawArrayList.indexOf(o);
}
@Override
public int lastIndexOf(Object o) {
return this.rawArrayList.lastIndexOf(o);
}
@Override
public ListIterator<Object> listIterator() {
return this.rawArrayList.listIterator();
}
@Override
public ListIterator<Object> listIterator(int index) {
return this.rawArrayList.listIterator(index);
}
@Override
public List<Object> subList(int fromIndex, int toIndex) {
return this.rawArrayList.subList(fromIndex, toIndex);
}
}