151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson/*
251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson * Copyright (C) 2010 The Android Open Source Project
351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson *
451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson * Licensed under the Apache License, Version 2.0 (the "License");
551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson * you may not use this file except in compliance with the License.
651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson * You may obtain a copy of the License at
751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson *
851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson *      http://www.apache.org/licenses/LICENSE-2.0
951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson *
1051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson * Unless required by applicable law or agreed to in writing, software
1151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS,
1251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson * See the License for the specific language governing permissions and
1451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson * limitations under the License.
1551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson */
1651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
1751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilsonpackage org.json;
1851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
193ad786880c88955a0e92610d24bb9bbe51b0e14cElliott Hughesimport java.lang.reflect.Array;
2051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilsonimport java.util.ArrayList;
2151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilsonimport java.util.Collection;
223ad786880c88955a0e92610d24bb9bbe51b0e14cElliott Hughesimport java.util.Iterator;
237365de1056414750d0a7d1fdd26025fd247f0d04Jesse Wilsonimport java.util.List;
2451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
2551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson// Note: this class was written without inspecting the non-free org.json sourcecode.
2651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
2751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson/**
28334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson * A dense indexed sequence of values. Values may be any mix of
29334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson * {@link JSONObject JSONObjects}, other {@link JSONArray JSONArrays}, Strings,
30334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson * Booleans, Integers, Longs, Doubles, {@code null} or {@link JSONObject#NULL}.
31334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson * Values may not be {@link Double#isNaN() NaNs}, {@link Double#isInfinite()
32334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson * infinities}, or of any type not listed here.
33334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson *
34334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson * <p>{@code JSONArray} has the same type coercion behavior and
35334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson * optional/mandatory accessors as {@link JSONObject}. See that class'
36334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson * documentation for details.
37334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson *
38334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson * <p><strong>Warning:</strong> this class represents null in two incompatible
39334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson * ways: the standard Java {@code null} reference, and the sentinel value {@link
4095cf9534436835291927cb4bcb36842731319da8Jesse Wilson * JSONObject#NULL}. In particular, {@code get} fails if the requested index
41334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson * holds the null reference, but succeeds if it holds {@code JSONObject.NULL}.
42334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson *
43334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson * <p>Instances of this class are not thread safe. Although this class is
44334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson * nonfinal, it was not designed for inheritance and should not be subclassed.
45334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson * In particular, self-use by overridable methods is not specified. See
46334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson * <i>Effective Java</i> Item 17, "Design and Document or inheritance or else
47334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson * prohibit it" for further information.
4851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson */
4951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilsonpublic class JSONArray {
5051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
5151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    private final List<Object> values;
5251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
53334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson    /**
54334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * Creates a {@code JSONArray} with no values.
55334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     */
5651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public JSONArray() {
5751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        values = new ArrayList<Object>();
5851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
5951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
60334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson    /**
61334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * Creates a new {@code JSONArray} by copying all values from the given
62334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * collection.
63334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     *
64334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * @param copyFrom a collection whose values are of supported types.
65334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     *     Unsupported values are not permitted and will yield an array in an
66334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     *     inconsistent state.
67334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     */
6851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    /* Accept a raw type for API compatibility */
6951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public JSONArray(Collection copyFrom) {
7051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        this();
713ad786880c88955a0e92610d24bb9bbe51b0e14cElliott Hughes        if (copyFrom != null) {
723ad786880c88955a0e92610d24bb9bbe51b0e14cElliott Hughes            for (Iterator it = copyFrom.iterator(); it.hasNext();) {
733ad786880c88955a0e92610d24bb9bbe51b0e14cElliott Hughes                put(JSONObject.wrap(it.next()));
743ad786880c88955a0e92610d24bb9bbe51b0e14cElliott Hughes            }
753ad786880c88955a0e92610d24bb9bbe51b0e14cElliott Hughes        }
7651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
7751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
78334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson    /**
79334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * Creates a new {@code JSONArray} with values from the next array in the
80334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * tokener.
81334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     *
82334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * @param readFrom a tokener whose nextValue() method will yield a
83334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     *     {@code JSONArray}.
84334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * @throws JSONException if the parse fails or doesn't yield a
85334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     *     {@code JSONArray}.
86334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     */
8751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public JSONArray(JSONTokener readFrom) throws JSONException {
8851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        /*
8951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson         * Getting the parser to populate this could get tricky. Instead, just
9051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson         * parse to temporary JSONArray and then steal the data from that.
9151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson         */
9251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        Object object = readFrom.nextValue();
9351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        if (object instanceof JSONArray) {
9451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson            values = ((JSONArray) object).values;
9551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        } else {
9651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson            throw JSON.typeMismatch(object, "JSONArray");
9751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        }
9851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
9951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
100334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson    /**
101334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * Creates a new {@code JSONArray} with values from the JSON string.
102334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     *
103334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * @param json a JSON-encoded string containing an array.
104334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * @throws JSONException if the parse fails or doesn't yield a {@code
105334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     *     JSONArray}.
106334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     */
10751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public JSONArray(String json) throws JSONException {
10851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        this(new JSONTokener(json));
10951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
11051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
111334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson    /**
1123ad786880c88955a0e92610d24bb9bbe51b0e14cElliott Hughes     * Creates a new {@code JSONArray} with values from the given primitive array.
1133ad786880c88955a0e92610d24bb9bbe51b0e14cElliott Hughes     */
1143ad786880c88955a0e92610d24bb9bbe51b0e14cElliott Hughes    public JSONArray(Object array) throws JSONException {
1153ad786880c88955a0e92610d24bb9bbe51b0e14cElliott Hughes        if (!array.getClass().isArray()) {
1163ad786880c88955a0e92610d24bb9bbe51b0e14cElliott Hughes            throw new JSONException("Not a primitive array: " + array.getClass());
1173ad786880c88955a0e92610d24bb9bbe51b0e14cElliott Hughes        }
1183ad786880c88955a0e92610d24bb9bbe51b0e14cElliott Hughes        final int length = Array.getLength(array);
1193ad786880c88955a0e92610d24bb9bbe51b0e14cElliott Hughes        values = new ArrayList<Object>(length);
1203ad786880c88955a0e92610d24bb9bbe51b0e14cElliott Hughes        for (int i = 0; i < length; ++i) {
1213ad786880c88955a0e92610d24bb9bbe51b0e14cElliott Hughes            put(JSONObject.wrap(Array.get(array, i)));
1223ad786880c88955a0e92610d24bb9bbe51b0e14cElliott Hughes        }
1233ad786880c88955a0e92610d24bb9bbe51b0e14cElliott Hughes    }
1243ad786880c88955a0e92610d24bb9bbe51b0e14cElliott Hughes
1253ad786880c88955a0e92610d24bb9bbe51b0e14cElliott Hughes    /**
126334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * Returns the number of values in this array.
127334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     */
12851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public int length() {
12951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        return values.size();
13051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
13151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
132334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson    /**
133334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * Appends {@code value} to the end of this array.
134334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     *
135334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * @return this array.
136334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     */
13751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public JSONArray put(boolean value) {
13851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        values.add(value);
13951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        return this;
14051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
14151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
142334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson    /**
143334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * Appends {@code value} to the end of this array.
144334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     *
145334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * @param value a finite value. May not be {@link Double#isNaN() NaNs} or
146334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     *     {@link Double#isInfinite() infinities}.
147334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * @return this array.
148334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     */
14951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public JSONArray put(double value) throws JSONException {
15051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        values.add(JSON.checkDouble(value));
15151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        return this;
15251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
15351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
154334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson    /**
155334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * Appends {@code value} to the end of this array.
156334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     *
157334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * @return this array.
158334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     */
15951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public JSONArray put(int value) {
16051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        values.add(value);
16151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        return this;
16251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
16351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
164334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson    /**
165334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * Appends {@code value} to the end of this array.
166334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     *
167334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * @return this array.
168334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     */
16951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public JSONArray put(long value) {
17051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        values.add(value);
17151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        return this;
17251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
17351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
174334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson    /**
175334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * Appends {@code value} to the end of this array.
176334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     *
177334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * @param value a {@link JSONObject}, {@link JSONArray}, String, Boolean,
178334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     *     Integer, Long, Double, {@link JSONObject#NULL}, or {@code null}. May
179334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     *     not be {@link Double#isNaN() NaNs} or {@link Double#isInfinite()
180334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     *     infinities}. Unsupported values are not permitted and will cause the
181334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     *     array to be in an inconsistent state.
182334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * @return this array.
183334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     */
18451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public JSONArray put(Object value) {
18551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        values.add(value);
18651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        return this;
18751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
18851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
189334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson    /**
1902ea1d56a1f70aeb0441209cda10756a301474bf4Narayan Kamath     * Same as {@link #put}, with added validity checks.
1912ea1d56a1f70aeb0441209cda10756a301474bf4Narayan Kamath     */
1922ea1d56a1f70aeb0441209cda10756a301474bf4Narayan Kamath    void checkedPut(Object value) throws JSONException {
1932ea1d56a1f70aeb0441209cda10756a301474bf4Narayan Kamath        if (value instanceof Number) {
1942ea1d56a1f70aeb0441209cda10756a301474bf4Narayan Kamath            JSON.checkDouble(((Number) value).doubleValue());
1952ea1d56a1f70aeb0441209cda10756a301474bf4Narayan Kamath        }
1962ea1d56a1f70aeb0441209cda10756a301474bf4Narayan Kamath
1972ea1d56a1f70aeb0441209cda10756a301474bf4Narayan Kamath        put(value);
1982ea1d56a1f70aeb0441209cda10756a301474bf4Narayan Kamath    }
1992ea1d56a1f70aeb0441209cda10756a301474bf4Narayan Kamath
2002ea1d56a1f70aeb0441209cda10756a301474bf4Narayan Kamath    /**
201334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * Sets the value at {@code index} to {@code value}, null padding this array
202334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * to the required length if necessary. If a value already exists at {@code
203334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * index}, it will be replaced.
204334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     *
205334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * @return this array.
206334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     */
20751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public JSONArray put(int index, boolean value) throws JSONException {
20851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        return put(index, (Boolean) value);
20951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
21051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
211334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson    /**
212334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * Sets the value at {@code index} to {@code value}, null padding this array
213334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * to the required length if necessary. If a value already exists at {@code
214334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * index}, it will be replaced.
215334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     *
216334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * @param value a finite value. May not be {@link Double#isNaN() NaNs} or
217334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     *     {@link Double#isInfinite() infinities}.
218334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * @return this array.
219334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     */
22051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public JSONArray put(int index, double value) throws JSONException {
22151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        return put(index, (Double) value);
22251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
22351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
224334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson    /**
225334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * Sets the value at {@code index} to {@code value}, null padding this array
226334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * to the required length if necessary. If a value already exists at {@code
227334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * index}, it will be replaced.
228334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     *
229334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * @return this array.
230334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     */
23151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public JSONArray put(int index, int value) throws JSONException {
23251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        return put(index, (Integer) value);
23351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
23451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
235334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson    /**
236334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * Sets the value at {@code index} to {@code value}, null padding this array
237334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * to the required length if necessary. If a value already exists at {@code
238334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * index}, it will be replaced.
239334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     *
240334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * @return this array.
241334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     */
24251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public JSONArray put(int index, long value) throws JSONException {
24351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        return put(index, (Long) value);
24451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
24551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
246334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson    /**
247334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * Sets the value at {@code index} to {@code value}, null padding this array
248334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * to the required length if necessary. If a value already exists at {@code
249334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * index}, it will be replaced.
250334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     *
251334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * @param value a {@link JSONObject}, {@link JSONArray}, String, Boolean,
252334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     *     Integer, Long, Double, {@link JSONObject#NULL}, or {@code null}. May
253334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     *     not be {@link Double#isNaN() NaNs} or {@link Double#isInfinite()
254334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     *     infinities}.
255334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * @return this array.
256334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     */
25751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public JSONArray put(int index, Object value) throws JSONException {
25851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        if (value instanceof Number) {
25951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson            // deviate from the original by checking all Numbers, not just floats & doubles
26051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson            JSON.checkDouble(((Number) value).doubleValue());
26151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        }
26251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        while (values.size() <= index) {
26351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson            values.add(null);
26451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        }
26551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        values.set(index, value);
26651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        return this;
26751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
26851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
269334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson    /**
270334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * Returns true if this array has no value at {@code index}, or if its value
271334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * is the {@code null} reference or {@link JSONObject#NULL}.
272334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     */
27351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public boolean isNull(int index) {
27451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        Object value = opt(index);
27551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        return value == null || value == JSONObject.NULL;
27651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
27751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
278334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson    /**
279334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * Returns the value at {@code index}.
280334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     *
281334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * @throws JSONException if this array has no value at {@code index}, or if
282334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     *     that value is the {@code null} reference. This method returns
283334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     *     normally if the value is {@code JSONObject#NULL}.
284334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     */
28551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public Object get(int index) throws JSONException {
28651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        try {
28751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson            Object value = values.get(index);
28851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson            if (value == null) {
28951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson                throw new JSONException("Value at " + index + " is null.");
29051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson            }
29151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson            return value;
29251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        } catch (IndexOutOfBoundsException e) {
293c65e388c419d43a69a954bfe9eaa8e447aed75d5John J. Aylward            throw new JSONException("Index " + index + " out of range [0.." + values.size() + ")", e);
29451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        }
29551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
29651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
297334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson    /**
298334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * Returns the value at {@code index}, or null if the array has no value
299334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * at {@code index}.
300334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     */
30151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public Object opt(int index) {
30251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        if (index < 0 || index >= values.size()) {
30351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson            return null;
30451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        }
30551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        return values.get(index);
30651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
30751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
308334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson    /**
309609601075ec0934cb23783c0b1194ecde041b6f5Elliott Hughes     * Removes and returns the value at {@code index}, or null if the array has no value
310609601075ec0934cb23783c0b1194ecde041b6f5Elliott Hughes     * at {@code index}.
311609601075ec0934cb23783c0b1194ecde041b6f5Elliott Hughes     */
312609601075ec0934cb23783c0b1194ecde041b6f5Elliott Hughes    public Object remove(int index) {
313609601075ec0934cb23783c0b1194ecde041b6f5Elliott Hughes        if (index < 0 || index >= values.size()) {
314609601075ec0934cb23783c0b1194ecde041b6f5Elliott Hughes            return null;
315609601075ec0934cb23783c0b1194ecde041b6f5Elliott Hughes        }
316609601075ec0934cb23783c0b1194ecde041b6f5Elliott Hughes        return values.remove(index);
317609601075ec0934cb23783c0b1194ecde041b6f5Elliott Hughes    }
318609601075ec0934cb23783c0b1194ecde041b6f5Elliott Hughes
319609601075ec0934cb23783c0b1194ecde041b6f5Elliott Hughes    /**
320334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * Returns the value at {@code index} if it exists and is a boolean or can
321334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * be coerced to a boolean.
322334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     *
323334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * @throws JSONException if the value at {@code index} doesn't exist or
324334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     *     cannot be coerced to a boolean.
325334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     */
32651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public boolean getBoolean(int index) throws JSONException {
32751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        Object object = get(index);
32851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        Boolean result = JSON.toBoolean(object);
32951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        if (result == null) {
33051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson            throw JSON.typeMismatch(index, object, "boolean");
33151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        }
33251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        return result;
33351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
33451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
335334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson    /**
336334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * Returns the value at {@code index} if it exists and is a boolean or can
337334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * be coerced to a boolean. Returns false otherwise.
338334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     */
33951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public boolean optBoolean(int index) {
34051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        return optBoolean(index, false);
34151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
34251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
343334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson    /**
344334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * Returns the value at {@code index} if it exists and is a boolean or can
345334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * be coerced to a boolean. Returns {@code fallback} otherwise.
346334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     */
34751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public boolean optBoolean(int index, boolean fallback) {
34851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        Object object = opt(index);
34951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        Boolean result = JSON.toBoolean(object);
35051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        return result != null ? result : fallback;
35151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
35251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
353334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson    /**
354334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * Returns the value at {@code index} if it exists and is a double or can
355334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * be coerced to a double.
356334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     *
357334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * @throws JSONException if the value at {@code index} doesn't exist or
358334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     *     cannot be coerced to a double.
359334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     */
36051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public double getDouble(int index) throws JSONException {
36151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        Object object = get(index);
36251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        Double result = JSON.toDouble(object);
36351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        if (result == null) {
36451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson            throw JSON.typeMismatch(index, object, "double");
36551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        }
36651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        return result;
36751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
36851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
369334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson    /**
370334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * Returns the value at {@code index} if it exists and is a double or can
371334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * be coerced to a double. Returns {@code NaN} otherwise.
372334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     */
37351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public double optDouble(int index) {
37451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        return optDouble(index, Double.NaN);
37551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
37651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
377334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson    /**
378334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * Returns the value at {@code index} if it exists and is a double or can
379334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * be coerced to a double. Returns {@code fallback} otherwise.
380334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     */
38151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public double optDouble(int index, double fallback) {
38251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        Object object = opt(index);
38351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        Double result = JSON.toDouble(object);
38451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        return result != null ? result : fallback;
38551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
38651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
387334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson    /**
388334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * Returns the value at {@code index} if it exists and is an int or
389334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * can be coerced to an int.
390334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     *
391334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * @throws JSONException if the value at {@code index} doesn't exist or
392334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     *     cannot be coerced to a int.
393334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     */
39451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public int getInt(int index) throws JSONException {
39551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        Object object = get(index);
39651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        Integer result = JSON.toInteger(object);
39751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        if (result == null) {
39851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson            throw JSON.typeMismatch(index, object, "int");
39951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        }
40051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        return result;
40151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
40251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
403334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson    /**
404334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * Returns the value at {@code index} if it exists and is an int or
405334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * can be coerced to an int. Returns 0 otherwise.
406334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     */
40751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public int optInt(int index) {
40851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        return optInt(index, 0);
40951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
41051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
411334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson    /**
412334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * Returns the value at {@code index} if it exists and is an int or
413334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * can be coerced to an int. Returns {@code fallback} otherwise.
414334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     */
41551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public int optInt(int index, int fallback) {
41651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        Object object = opt(index);
41751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        Integer result = JSON.toInteger(object);
41851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        return result != null ? result : fallback;
41951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
42051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
421334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson    /**
422334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * Returns the value at {@code index} if it exists and is a long or
423334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * can be coerced to a long.
424334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     *
425334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * @throws JSONException if the value at {@code index} doesn't exist or
426334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     *     cannot be coerced to a long.
427334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     */
42851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public long getLong(int index) throws JSONException {
42951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        Object object = get(index);
43051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        Long result = JSON.toLong(object);
43151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        if (result == null) {
43251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson            throw JSON.typeMismatch(index, object, "long");
43351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        }
43451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        return result;
43551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
43651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
437334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson    /**
438334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * Returns the value at {@code index} if it exists and is a long or
439334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * can be coerced to a long. Returns 0 otherwise.
440334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     */
44151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public long optLong(int index) {
44251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        return optLong(index, 0L);
44351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
44451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
445334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson    /**
446334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * Returns the value at {@code index} if it exists and is a long or
447334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * can be coerced to a long. Returns {@code fallback} otherwise.
448334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     */
44951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public long optLong(int index, long fallback) {
45051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        Object object = opt(index);
45151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        Long result = JSON.toLong(object);
45251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        return result != null ? result : fallback;
45351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
45451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
455334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson    /**
456334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * Returns the value at {@code index} if it exists, coercing it if
457334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * necessary.
458334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     *
459334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * @throws JSONException if no such value exists.
460334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     */
46151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public String getString(int index) throws JSONException {
46251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        Object object = get(index);
46351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        String result = JSON.toString(object);
46451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        if (result == null) {
46551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson            throw JSON.typeMismatch(index, object, "String");
46651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        }
46751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        return result;
46851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
46951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
470334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson    /**
471334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * Returns the value at {@code index} if it exists, coercing it if
472334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * necessary. Returns the empty string if no such value exists.
473334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     */
47451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public String optString(int index) {
47551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        return optString(index, "");
47651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
47751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
478334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson    /**
479334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * Returns the value at {@code index} if it exists, coercing it if
480334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * necessary. Returns {@code fallback} if no such value exists.
481334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     */
48251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public String optString(int index, String fallback) {
48351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        Object object = opt(index);
48451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        String result = JSON.toString(object);
48551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        return result != null ? result : fallback;
48651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
48751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
488334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson    /**
489334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * Returns the value at {@code index} if it exists and is a {@code
490334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * JSONArray}.
491334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     *
492334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * @throws JSONException if the value doesn't exist or is not a {@code
493334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     *     JSONArray}.
494334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     */
49551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public JSONArray getJSONArray(int index) throws JSONException {
49651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        Object object = get(index);
49751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        if (object instanceof JSONArray) {
49851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson            return (JSONArray) object;
49951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        } else {
50051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson            throw JSON.typeMismatch(index, object, "JSONArray");
50151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        }
50251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
50351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
504334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson    /**
505334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * Returns the value at {@code index} if it exists and is a {@code
506334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * JSONArray}. Returns null otherwise.
507334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     */
50851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public JSONArray optJSONArray(int index) {
50951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        Object object = opt(index);
51051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        return object instanceof JSONArray ? (JSONArray) object : null;
51151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
51251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
513334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson    /**
514334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * Returns the value at {@code index} if it exists and is a {@code
515334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * JSONObject}.
516334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     *
517334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * @throws JSONException if the value doesn't exist or is not a {@code
518334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     *     JSONObject}.
519334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     */
52051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public JSONObject getJSONObject(int index) throws JSONException {
52151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        Object object = get(index);
52251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        if (object instanceof JSONObject) {
52351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson            return (JSONObject) object;
52451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        } else {
52551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson            throw JSON.typeMismatch(index, object, "JSONObject");
52651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        }
52751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
52851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
529334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson    /**
530334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * Returns the value at {@code index} if it exists and is a {@code
531334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * JSONObject}. Returns null otherwise.
532334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     */
53351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public JSONObject optJSONObject(int index) {
53451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        Object object = opt(index);
53551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        return object instanceof JSONObject ? (JSONObject) object : null;
53651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
53751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
538334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson    /**
539334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * Returns a new object whose values are the values in this array, and whose
540334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * names are the values in {@code names}. Names and values are paired up by
541334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * index from 0 through to the shorter array's length. Names that are not
542334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * strings will be coerced to strings. This method returns null if either
543334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * array is empty.
544334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     */
54551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public JSONObject toJSONObject(JSONArray names) throws JSONException {
54651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        JSONObject result = new JSONObject();
54751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        int length = Math.min(names.length(), values.size());
54851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        if (length == 0) {
54951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson            return null;
55051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        }
55151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        for (int i = 0; i < length; i++) {
55251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson            String name = JSON.toString(names.opt(i));
55351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson            result.put(name, opt(i));
55451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        }
55551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        return result;
55651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
55751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
558334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson    /**
559334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * Returns a new string by alternating this array's values with {@code
560334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * separator}. This array's string values are quoted and have their special
561334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * characters escaped. For example, the array containing the strings '12"
562334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * pizza', 'taco' and 'soda' joined on '+' returns this:
563334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * <pre>"12\" pizza"+"taco"+"soda"</pre>
564334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     */
56551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public String join(String separator) throws JSONException {
56651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        JSONStringer stringer = new JSONStringer();
56751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        stringer.open(JSONStringer.Scope.NULL, "");
56851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        for (int i = 0, size = values.size(); i < size; i++) {
56951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson            if (i > 0) {
57051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson                stringer.out.append(separator);
57151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson            }
57251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson            stringer.value(values.get(i));
57351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        }
57451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        stringer.close(JSONStringer.Scope.NULL, JSONStringer.Scope.NULL, "");
57551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        return stringer.out.toString();
57651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
57751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
578334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson    /**
579334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * Encodes this array as a compact JSON string, such as:
580334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * <pre>[94043,90210]</pre>
581334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     */
58251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    @Override public String toString() {
58351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        try {
58451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson            JSONStringer stringer = new JSONStringer();
58551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson            writeTo(stringer);
58651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson            return stringer.toString();
58751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        } catch (JSONException e) {
58851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson            return null;
58951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        }
59051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
59151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
592334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson    /**
593334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * Encodes this array as a human readable JSON string for debugging, such
594334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * as:
595334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * <pre>
596334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * [
597334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     *     94043,
598334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     *     90210
599334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * ]</pre>
600334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     *
601334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     * @param indentSpaces the number of spaces to indent for each level of
602334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     *     nesting.
603334e613308e7e39d9f58e9efbb0ea491c5e18841Jesse Wilson     */
60451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public String toString(int indentSpaces) throws JSONException {
60551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        JSONStringer stringer = new JSONStringer(indentSpaces);
60651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        writeTo(stringer);
60751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        return stringer.toString();
60851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
60951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
61051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    void writeTo(JSONStringer stringer) throws JSONException {
61151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        stringer.array();
61251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        for (Object value : values) {
61351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson            stringer.value(value);
61451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        }
61551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        stringer.endArray();
61651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
61751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
61851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    @Override public boolean equals(Object o) {
61951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        return o instanceof JSONArray && ((JSONArray) o).values.equals(values);
62051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
62151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
62251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    @Override public int hashCode() {
62351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        // diverge from the original, which doesn't implement hashCode
62451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        return values.hashCode();
62551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
62651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson}
627