All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.xiaoleilu.hutool.json.JSONArray Maven / Gradle / Ivy

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 implements JSON, List{

	/** 持有原始数据的List */
	private final ArrayList rawArrayList;

	//-------------------------------------------------------------------------------------------------------------------- Constructor start
	/**
	 * 构造
	 */
	public JSONArray() {
		this.rawArrayList = new ArrayList();
	}

	/**
	 * 使用 {@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

	/**
	 * 值是否为null
	 *
	 * @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转为以separator为分界符的字符串
	 *
	 * @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 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[] 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 c) {
		for (Object obj : c) {
			this.add(obj);
		}
		return rawArrayList.addAll(c);
	}

	@Override
	public boolean addAll(int index, Collection 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 listIterator() {
		return this.rawArrayList.listIterator();
	}

	@Override
	public ListIterator listIterator(int index) {
		return this.rawArrayList.listIterator(index);
	}

	@Override
	public List subList(int fromIndex, int toIndex) {
		return this.rawArrayList.subList(fromIndex, toIndex);
	}
}