1 /*******************************************************************************
\r
2 * ============LICENSE_START==================================================
\r
4 * * ===========================================================================
\r
5 * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
\r
6 * * ===========================================================================
\r
7 * * Licensed under the Apache License, Version 2.0 (the "License");
\r
8 * * you may not use this file except in compliance with the License.
\r
9 * * You may obtain a copy of the License at
\r
11 * * http://www.apache.org/licenses/LICENSE-2.0
\r
13 * * Unless required by applicable law or agreed to in writing, software
\r
14 * * distributed under the License is distributed on an "AS IS" BASIS,
\r
15 * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
16 * * See the License for the specific language governing permissions and
\r
17 * * limitations under the License.
\r
18 * * ============LICENSE_END====================================================
\r
20 * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
\r
22 ******************************************************************************/
\r
26 import java.io.IOException;
\r
27 import java.io.StringWriter;
\r
28 import java.io.Writer;
\r
29 import java.lang.reflect.Array;
\r
30 import java.util.ArrayList;
\r
31 import java.util.Collection;
\r
32 import java.util.Iterator;
\r
33 import java.util.List;
\r
34 import java.util.Map;
\r
37 public class JSONArray {
\r
40 * The arrayList where the JSONArray's properties are kept.
\r
42 private final List<Object> myArrayList;
\r
45 * Construct an empty JSONArray.
\r
47 public JSONArray() {
\r
48 this.myArrayList = new ArrayList<Object>();
\r
52 * Construct a JSONArray from a JSONTokener.
\r
56 * @throws JSONException
\r
57 * If there is a syntax error.
\r
59 public JSONArray(JSONTokener x) throws JSONException {
\r
61 if (x.nextClean() != '[') {
\r
62 throw x.syntaxError("A JSONArray text must start with '['");
\r
64 if (x.nextClean() != ']') {
\r
67 if (x.nextClean() == ',') {
\r
69 this.myArrayList.add(JSONObject.NULL);
\r
72 this.myArrayList.add(x.nextValue());
\r
74 switch (x.nextClean()) {
\r
77 if (x.nextClean() == ']') {
\r
85 throw x.syntaxError("Expected a ',' or ']'");
\r
92 * Construct a JSONArray from a source JSON text.
\r
95 * A string that begins with <code>[</code> <small>(left
\r
96 * bracket)</small> and ends with <code>]</code>
\r
97 * <small>(right bracket)</small>.
\r
98 * @throws JSONException
\r
99 * If there is a syntax error.
\r
101 public JSONArray(String source) throws JSONException {
\r
102 this(new JSONTokener(source));
\r
106 * Construct a JSONArray from a Collection.
\r
108 * @param collection
\r
111 public JSONArray(Collection<Object> collection) {
\r
112 this.myArrayList = new ArrayList<Object>();
\r
113 if (collection != null) {
\r
114 Iterator<Object> iter = collection.iterator();
\r
115 while (iter.hasNext()) {
\r
116 this.myArrayList.add(JSONObject.wrap(iter.next()));
\r
122 * Construct a JSONArray from an array
\r
124 * @throws JSONException
\r
127 public JSONArray(Object array) throws JSONException {
\r
129 if (array.getClass().isArray()) {
\r
130 int length = Array.getLength(array);
\r
131 for (int i = 0; i < length; i += 1) {
\r
132 this.put(JSONObject.wrap(Array.get(array, i)));
\r
135 throw new JSONException(
\r
136 "JSONArray initial value should be a string or collection or array.");
\r
141 * Get the object value associated with an index.
\r
144 * The index must be between 0 and length() - 1.
\r
145 * @return An object value.
\r
146 * @throws JSONException
\r
147 * If there is no value for the index.
\r
149 public Object get(int index) throws JSONException {
\r
150 Object object = this.opt(index);
\r
151 if (object == null) {
\r
152 throw new JSONException("JSONArray[" + index + "] not found.");
\r
158 * Get the boolean value associated with an index. The string values "true"
\r
159 * and "false" are converted to boolean.
\r
162 * The index must be between 0 and length() - 1.
\r
163 * @return The truth.
\r
164 * @throws JSONException
\r
165 * If there is no value for the index or if the value is not
\r
166 * convertible to boolean.
\r
168 public boolean getBoolean(int index) throws JSONException {
\r
169 Object object = this.get(index);
\r
170 if (object.equals(Boolean.FALSE)
\r
171 || (object instanceof String && ((String) object)
\r
172 .equalsIgnoreCase("false"))) {
\r
174 } else if (object.equals(Boolean.TRUE)
\r
175 || (object instanceof String && ((String) object)
\r
176 .equalsIgnoreCase("true"))) {
\r
179 throw new JSONException("JSONArray[" + index + "] is not a boolean.");
\r
183 * Get the double value associated with an index.
\r
186 * The index must be between 0 and length() - 1.
\r
187 * @return The value.
\r
188 * @throws JSONException
\r
189 * If the key is not found or if the value cannot be converted
\r
192 public double getDouble(int index) throws JSONException {
\r
193 Object object = this.get(index);
\r
195 return object instanceof Number ? ((Number) object).doubleValue()
\r
196 : Double.parseDouble((String) object);
\r
197 } catch (Exception e) {
\r
198 throw new JSONException("JSONArray[" + index + "] is not a number.");
\r
203 * Get the int value associated with an index.
\r
206 * The index must be between 0 and length() - 1.
\r
207 * @return The value.
\r
208 * @throws JSONException
\r
209 * If the key is not found or if the value is not a number.
\r
211 public int getInt(int index) throws JSONException {
\r
212 Object object = this.get(index);
\r
214 return object instanceof Number ? ((Number) object).intValue()
\r
215 : Integer.parseInt((String) object);
\r
216 } catch (Exception e) {
\r
217 throw new JSONException("JSONArray[" + index + "] is not a number.");
\r
222 * Get the JSONArray associated with an index.
\r
225 * The index must be between 0 and length() - 1.
\r
226 * @return A JSONArray value.
\r
227 * @throws JSONException
\r
228 * If there is no value for the index. or if the value is not a
\r
231 public JSONArray getJSONArray(int index) throws JSONException {
\r
232 Object object = this.get(index);
\r
233 if (object instanceof JSONArray) {
\r
234 return (JSONArray) object;
\r
236 throw new JSONException("JSONArray[" + index + "] is not a JSONArray.");
\r
240 * Get the JSONObject associated with an index.
\r
244 * @return A JSONObject value.
\r
245 * @throws JSONException
\r
246 * If there is no value for the index or if the value is not a
\r
249 public JSONObject getJSONObject(int index) throws JSONException {
\r
250 Object object = this.get(index);
\r
251 if (object instanceof JSONObject) {
\r
252 return (JSONObject) object;
\r
254 throw new JSONException("JSONArray[" + index + "] is not a JSONObject.");
\r
258 * Get the long value associated with an index.
\r
261 * The index must be between 0 and length() - 1.
\r
262 * @return The value.
\r
263 * @throws JSONException
\r
264 * If the key is not found or if the value cannot be converted
\r
267 public long getLong(int index) throws JSONException {
\r
268 Object object = this.get(index);
\r
270 return object instanceof Number ? ((Number) object).longValue()
\r
271 : Long.parseLong((String) object);
\r
272 } catch (Exception e) {
\r
273 throw new JSONException("JSONArray[" + index + "] is not a number.");
\r
278 * Get the string associated with an index.
\r
281 * The index must be between 0 and length() - 1.
\r
282 * @return A string value.
\r
283 * @throws JSONException
\r
284 * If there is no string value for the index.
\r
286 public String getString(int index) throws JSONException {
\r
287 Object object = this.get(index);
\r
288 if (object instanceof String) {
\r
289 return (String) object;
\r
291 throw new JSONException("JSONArray[" + index + "] not a string.");
\r
295 * Determine if the value is null.
\r
298 * The index must be between 0 and length() - 1.
\r
299 * @return true if the value at the index is null, or if there is no value.
\r
301 public boolean isNull(int index) {
\r
302 return JSONObject.NULL.equals(this.opt(index));
\r
306 * Make a string from the contents of this JSONArray. The
\r
307 * <code>separator</code> string is inserted between each element. Warning:
\r
308 * This method assumes that the data structure is acyclical.
\r
311 * A string that will be inserted between the elements.
\r
312 * @return a string.
\r
313 * @throws JSONException
\r
314 * If the array contains an invalid number.
\r
316 public String join(String separator) throws JSONException {
\r
317 int len = this.length();
\r
318 StringBuffer sb = new StringBuffer();
\r
320 for (int i = 0; i < len; i += 1) {
\r
322 sb.append(separator);
\r
324 sb.append(JSONObject.valueToString(this.myArrayList.get(i)));
\r
326 return sb.toString();
\r
330 * Get the number of elements in the JSONArray, included nulls.
\r
332 * @return The length (or size).
\r
334 public int length() {
\r
335 return this.myArrayList.size();
\r
339 * Get the optional object value associated with an index.
\r
342 * The index must be between 0 and length() - 1.
\r
343 * @return An object value, or null if there is no object at that index.
\r
345 public Object opt(int index) {
\r
346 return (index < 0 || index >= this.length()) ? null : this.myArrayList
\r
351 * Get the optional boolean value associated with an index. It returns false
\r
352 * if there is no value at that index, or if the value is not Boolean.TRUE
\r
353 * or the String "true".
\r
356 * The index must be between 0 and length() - 1.
\r
357 * @return The truth.
\r
359 public boolean optBoolean(int index) {
\r
360 return this.optBoolean(index, false);
\r
364 * Get the optional boolean value associated with an index. It returns the
\r
365 * defaultValue if there is no value at that index or if it is not a Boolean
\r
366 * or the String "true" or "false" (case insensitive).
\r
369 * The index must be between 0 and length() - 1.
\r
370 * @param defaultValue
\r
371 * A boolean default.
\r
372 * @return The truth.
\r
374 public boolean optBoolean(int index, boolean defaultValue) {
\r
376 return this.getBoolean(index);
\r
377 } catch (Exception e) {
\r
378 return defaultValue;
\r
383 * Get the optional double value associated with an index. NaN is returned
\r
384 * if there is no value for the index, or if the value is not a number and
\r
385 * cannot be converted to a number.
\r
388 * The index must be between 0 and length() - 1.
\r
389 * @return The value.
\r
391 public double optDouble(int index) {
\r
392 return this.optDouble(index, Double.NaN);
\r
396 * Get the optional double value associated with an index. The defaultValue
\r
397 * is returned if there is no value for the index, or if the value is not a
\r
398 * number and cannot be converted to a number.
\r
402 * @param defaultValue
\r
403 * The default value.
\r
404 * @return The value.
\r
406 public double optDouble(int index, double defaultValue) {
\r
408 return this.getDouble(index);
\r
409 } catch (Exception e) {
\r
410 return defaultValue;
\r
415 * Get the optional int value associated with an index. Zero is returned if
\r
416 * there is no value for the index, or if the value is not a number and
\r
417 * cannot be converted to a number.
\r
420 * The index must be between 0 and length() - 1.
\r
421 * @return The value.
\r
423 public int optInt(int index) {
\r
424 return this.optInt(index, 0);
\r
428 * Get the optional int value associated with an index. The defaultValue is
\r
429 * returned if there is no value for the index, or if the value is not a
\r
430 * number and cannot be converted to a number.
\r
433 * The index must be between 0 and length() - 1.
\r
434 * @param defaultValue
\r
435 * The default value.
\r
436 * @return The value.
\r
438 public int optInt(int index, int defaultValue) {
\r
440 return this.getInt(index);
\r
441 } catch (Exception e) {
\r
442 return defaultValue;
\r
447 * Get the optional JSONArray associated with an index.
\r
451 * @return A JSONArray value, or null if the index has no value, or if the
\r
452 * value is not a JSONArray.
\r
454 public JSONArray optJSONArray(int index) {
\r
455 Object o = this.opt(index);
\r
456 return o instanceof JSONArray ? (JSONArray) o : null;
\r
460 * Get the optional JSONObject associated with an index. Null is returned if
\r
461 * the key is not found, or null if the index has no value, or if the value
\r
462 * is not a JSONObject.
\r
465 * The index must be between 0 and length() - 1.
\r
466 * @return A JSONObject value.
\r
468 public JSONObject optJSONObject(int index) {
\r
469 Object o = this.opt(index);
\r
470 return o instanceof JSONObject ? (JSONObject) o : null;
\r
474 * Get the optional long value associated with an index. Zero is returned if
\r
475 * there is no value for the index, or if the value is not a number and
\r
476 * cannot be converted to a number.
\r
479 * The index must be between 0 and length() - 1.
\r
480 * @return The value.
\r
482 public long optLong(int index) {
\r
483 return this.optLong(index, 0);
\r
487 * Get the optional long value associated with an index. The defaultValue is
\r
488 * returned if there is no value for the index, or if the value is not a
\r
489 * number and cannot be converted to a number.
\r
492 * The index must be between 0 and length() - 1.
\r
493 * @param defaultValue
\r
494 * The default value.
\r
495 * @return The value.
\r
497 public long optLong(int index, long defaultValue) {
\r
499 return this.getLong(index);
\r
500 } catch (Exception e) {
\r
501 return defaultValue;
\r
506 * Get the optional string value associated with an index. It returns an
\r
507 * empty string if there is no value at that index. If the value is not a
\r
508 * string and is not null, then it is coverted to a string.
\r
511 * The index must be between 0 and length() - 1.
\r
512 * @return A String value.
\r
514 public String optString(int index) {
\r
515 return this.optString(index, "");
\r
519 * Get the optional string associated with an index. The defaultValue is
\r
520 * returned if the key is not found.
\r
523 * The index must be between 0 and length() - 1.
\r
524 * @param defaultValue
\r
525 * The default value.
\r
526 * @return A String value.
\r
528 public String optString(int index, String defaultValue) {
\r
529 Object object = this.opt(index);
\r
530 return JSONObject.NULL.equals(object) ? defaultValue : object
\r
535 * Append a boolean value. This increases the array's length by one.
\r
541 public JSONArray put(boolean value) {
\r
542 this.put(value ? Boolean.TRUE : Boolean.FALSE);
\r
547 * Put a value in the JSONArray, where the value will be a JSONArray which
\r
548 * is produced from a Collection.
\r
551 * A Collection value.
\r
554 public JSONArray put(Collection<Object> value) {
\r
555 this.put(new JSONArray(value));
\r
560 * Append a double value. This increases the array's length by one.
\r
564 * @throws JSONException
\r
565 * if the value is not finite.
\r
568 public JSONArray put(double value) throws JSONException {
\r
569 Double d = new Double(value);
\r
570 JSONObject.testValidity(d);
\r
576 * Append an int value. This increases the array's length by one.
\r
582 public JSONArray put(int value) {
\r
583 this.put(new Integer(value));
\r
588 * Append an long value. This increases the array's length by one.
\r
594 public JSONArray put(long value) {
\r
595 this.put(new Long(value));
\r
600 * Put a value in the JSONArray, where the value will be a JSONObject which
\r
601 * is produced from a Map.
\r
607 public JSONArray put(Map<String,Object> value) {
\r
608 this.put(new JSONObject(value));
\r
613 * Append an object value. This increases the array's length by one.
\r
616 * An object value. The value should be a Boolean, Double,
\r
617 * Integer, JSONArray, JSONObject, Long, or String, or the
\r
618 * JSONObject.NULL object.
\r
621 public JSONArray put(Object value) {
\r
622 this.myArrayList.add(value);
\r
627 * Put or replace a boolean value in the JSONArray. If the index is greater
\r
628 * than the length of the JSONArray, then null elements will be added as
\r
629 * necessary to pad it out.
\r
636 * @throws JSONException
\r
637 * If the index is negative.
\r
639 public JSONArray put(int index, boolean value) throws JSONException {
\r
640 this.put(index, value ? Boolean.TRUE : Boolean.FALSE);
\r
645 * Put a value in the JSONArray, where the value will be a JSONArray which
\r
646 * is produced from a Collection.
\r
651 * A Collection value.
\r
653 * @throws JSONException
\r
654 * If the index is negative or if the value is not finite.
\r
656 public JSONArray put(int index, Collection<Object> value) throws JSONException {
\r
657 this.put(index, new JSONArray(value));
\r
662 * Put or replace a double value. If the index is greater than the length of
\r
663 * the JSONArray, then null elements will be added as necessary to pad it
\r
671 * @throws JSONException
\r
672 * If the index is negative or if the value is not finite.
\r
674 public JSONArray put(int index, double value) throws JSONException {
\r
675 this.put(index, new Double(value));
\r
680 * Put or replace an int value. If the index is greater than the length of
\r
681 * the JSONArray, then null elements will be added as necessary to pad it
\r
689 * @throws JSONException
\r
690 * If the index is negative.
\r
692 public JSONArray put(int index, int value) throws JSONException {
\r
693 this.put(index, new Integer(value));
\r
698 * Put or replace a long value. If the index is greater than the length of
\r
699 * the JSONArray, then null elements will be added as necessary to pad it
\r
707 * @throws JSONException
\r
708 * If the index is negative.
\r
710 public JSONArray put(int index, long value) throws JSONException {
\r
711 this.put(index, new Long(value));
\r
716 * Put a value in the JSONArray, where the value will be a JSONObject that
\r
717 * is produced from a Map.
\r
724 * @throws JSONException
\r
725 * If the index is negative or if the the value is an invalid
\r
728 public JSONArray put(int index, Map<String,Object> value) throws JSONException {
\r
729 this.put(index, new JSONObject(value));
\r
734 * Put or replace an object value in the JSONArray. If the index is greater
\r
735 * than the length of the JSONArray, then null elements will be added as
\r
736 * necessary to pad it out.
\r
741 * The value to put into the array. The value should be a
\r
742 * Boolean, Double, Integer, JSONArray, JSONObject, Long, or
\r
743 * String, or the JSONObject.NULL object.
\r
745 * @throws JSONException
\r
746 * If the index is negative or if the the value is an invalid
\r
749 public JSONArray put(int index, Object value) throws JSONException {
\r
750 JSONObject.testValidity(value);
\r
752 throw new JSONException("JSONArray[" + index + "] not found.");
\r
754 if (index < this.length()) {
\r
755 this.myArrayList.set(index, value);
\r
757 while (index != this.length()) {
\r
758 this.put(JSONObject.NULL);
\r
766 * Remove an index and close the hole.
\r
769 * The index of the element to be removed.
\r
770 * @return The value that was associated with the index, or null if there
\r
773 public Object remove(int index) {
\r
774 Object o = this.opt(index);
\r
775 this.myArrayList.remove(index);
\r
780 * Produce a JSONObject by combining a JSONArray of names with the values of
\r
784 * A JSONArray containing a list of key strings. These will be
\r
785 * paired with the values.
\r
786 * @return A JSONObject, or null if there are no names or if this JSONArray
\r
788 * @throws JSONException
\r
789 * If any of the names are null.
\r
791 public JSONObject toJSONObject(JSONArray names) throws JSONException {
\r
792 if (names == null || names.length() == 0 || this.length() == 0) {
\r
795 JSONObject jo = new JSONObject();
\r
796 for (int i = 0; i < names.length(); i += 1) {
\r
797 jo.put(names.getString(i), this.opt(i));
\r
803 * Make a JSON text of this JSONArray. For compactness, no unnecessary
\r
804 * whitespace is added. If it is not possible to produce a syntactically
\r
805 * correct JSON text then null will be returned instead. This could occur if
\r
806 * the array contains an invalid number.
\r
808 * Warning: This method assumes that the data structure is acyclical.
\r
810 * @return a printable, displayable, transmittable representation of the
\r
813 public String toString() {
\r
815 return this.toString(0);
\r
816 } catch (Exception e) {
\r
822 * Make a prettyprinted JSON text of this JSONArray. Warning: This method
\r
823 * assumes that the data structure is acyclical.
\r
825 * @param indentFactor
\r
826 * The number of spaces to add to each level of indentation.
\r
827 * @return a printable, displayable, transmittable representation of the
\r
828 * object, beginning with <code>[</code> <small>(left
\r
829 * bracket)</small> and ending with <code>]</code>
\r
830 * <small>(right bracket)</small>.
\r
831 * @throws JSONException
\r
833 public String toString(int indentFactor) throws JSONException {
\r
834 StringWriter sw = new StringWriter();
\r
835 synchronized (sw.getBuffer()) {
\r
836 return this.write(sw, indentFactor, 0).toString();
\r
841 * Write the contents of the JSONArray as JSON text to a writer. For
\r
842 * compactness, no whitespace is added.
\r
844 * Warning: This method assumes that the data structure is acyclical.
\r
846 * @return The writer.
\r
847 * @throws JSONException
\r
849 public Writer write(Writer writer) throws JSONException {
\r
850 return this.write(writer, 0, 0);
\r
854 * Write the contents of the JSONArray as JSON text to a writer. For
\r
855 * compactness, no whitespace is added.
\r
857 * Warning: This method assumes that the data structure is acyclical.
\r
859 * @param indentFactor
\r
860 * The number of spaces to add to each level of indentation.
\r
862 * The indention of the top level.
\r
863 * @return The writer.
\r
864 * @throws JSONException
\r
866 Writer write(Writer writer, int indentFactor, int indent)
\r
867 throws JSONException {
\r
869 boolean commanate = false;
\r
870 int length = this.length();
\r
874 JSONObject.writeValue(writer, this.myArrayList.get(0),
\r
875 indentFactor, indent);
\r
876 } else if (length != 0) {
\r
877 final int newindent = indent + indentFactor;
\r
879 for (int i = 0; i < length; i += 1) {
\r
883 if (indentFactor > 0) {
\r
884 writer.write('\n');
\r
886 JSONObject.indent(writer, newindent);
\r
887 JSONObject.writeValue(writer, this.myArrayList.get(i),
\r
888 indentFactor, newindent);
\r
891 if (indentFactor > 0) {
\r
892 writer.write('\n');
\r
894 JSONObject.indent(writer, indent);
\r
898 } catch (IOException e) {
\r
899 throw new JSONException(e);
\r