001package org.json;
002
003/*
004Copyright (c) 2002 JSON.org
005
006Permission is hereby granted, free of charge, to any person obtaining a copy
007of this software and associated documentation files (the "Software"), to deal
008in the Software without restriction, including without limitation the rights
009to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
010copies of the Software, and to permit persons to whom the Software is
011furnished to do so, subject to the following conditions:
012
013The above copyright notice and this permission notice shall be included in all
014copies or substantial portions of the Software.
015
016The Software shall be used for Good, not Evil.
017
018THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
019IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
020FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
021AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
022LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
023OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
024SOFTWARE.
025 */
026import java.io.IOException;
027import java.io.Writer;
028import java.lang.reflect.Field;
029import java.lang.reflect.Method;
030import java.lang.reflect.Modifier;
031import java.util.Collection;
032import java.util.HashMap;
033import java.util.Iterator;
034import java.util.Locale;
035import java.util.Map;
036import java.util.TreeSet;
037
038/**
039 * A JSONObject is an unordered collection of name/value pairs. Its
040 * external form is a string wrapped in curly braces with colons between the
041 * names and values, and commas between the values and names. The internal form
042 * is an object having <code>get</code> and <code>opt</code> methods for
043 * accessing the values by name, and <code>put</code> methods for adding or
044 * replacing values by name. The values can be any of these types:
045 * <code>Boolean</code>, <code>JSONArray</code>, <code>JSONObject</code>,
046 * <code>Number</code>, <code>String</code>, or the <code>JSONObject.NULL</code>
047 * object. A JSONObject constructor can be used to convert an external form
048 * JSON text into an internal form whose values can be retrieved with the
049 * <code>get</code> and <code>opt</code> methods, or to convert values into a
050 * JSON text using the <code>put</code> and <code>toString</code> methods.
051 * A <code>get</code> method returns a value if one can be found, and throws an
052 * exception if one cannot be found. An <code>opt</code> method returns a
053 * default value instead of throwing an exception, and so is useful for
054 * obtaining optional values.
055 * <p>
056 * The generic <code>get()</code> and <code>opt()</code> methods return an
057 * object, which you can cast or query for type. There are also typed
058 * <code>get</code> and <code>opt</code> methods that do type checking and type
059 * coercion for you.
060 * <p>
061 * The <code>put</code> methods adds values to an object. For example, <pre>
062 *     myString = new JSONObject().put("JSON", "Hello, World!").toString();</pre>
063 * produces the string <code>{"JSON": "Hello, World"}</code>.
064 * <p>
065 * The texts produced by the <code>toString</code> methods strictly conform to
066 * the JSON syntax rules.
067 * The constructors are more forgiving in the texts they will accept:
068 * <ul>
069 * <li>An extra <code>,</code>&nbsp;<small>(comma)</small> may appear just
070 *     before the closing brace.</li>
071 * <li>Strings may be quoted with <code>'</code>&nbsp;<small>(single
072 *     quote)</small>.</li>
073 * <li>Strings do not need to be quoted at all if they do not begin with a quote
074 *     or single quote, and if they do not contain leading or trailing spaces,
075 *     and if they do not contain any of these characters:
076 *     <code>{ } [ ] / \ : , = ; #</code> and if they do not look like numbers
077 *     and if they are not the reserved words <code>true</code>,
078 *     <code>false</code>, or <code>null</code>.</li>
079 * <li>Keys can be followed by <code>=</code> or <code>=&gt;</code> as well as
080 *     by <code>:</code>.</li>
081 * <li>Values can be followed by <code>;</code> <small>(semicolon)</small> as
082 *     well as by <code>,</code> <small>(comma)</small>.</li>
083 * <li>Numbers may have the <code>0x-</code> <small>(hex)</small> prefix.</li>
084 * </ul>
085 * @author JSON.org
086@version $Id$
087@since Ptolemy II 10.0
088 * @version 2010-05-17
089 */
090public class JSONObject {
091
092    /**
093     * JSONObject.NULL is equivalent to the value that JavaScript calls null,
094     * whilst Java's null is equivalent to the value that JavaScript calls
095     * undefined.
096     */
097    private static final class Null {
098
099        /**
100         * There is only intended to be a single instance of the NULL object,
101         * so the clone method returns itself.
102         * @return     NULL.
103         */
104        @Override
105        protected final Object clone() {
106            return this;
107        }
108
109        /**
110         * A Null object is equal to the null value and to itself.
111         * @param object    An object to test for nullness.
112         * @return true if the object parameter is the JSONObject.NULL object
113         *  or null.
114         */
115        @Override
116        public boolean equals(Object object) {
117            return object == null || object == this;
118        }
119
120        /**
121         * Get the "null" string value.
122         * @return The string "null".
123         */
124        @Override
125        public String toString() {
126            return "null";
127        }
128    }
129
130    /**
131     * The map where the JSONObject's properties are kept.
132     */
133    private Map map;
134
135    /**
136     * It is sometimes more convenient and less ambiguous to have a
137     * <code>NULL</code> object than to use Java's <code>null</code> value.
138     * <code>JSONObject.NULL.equals(null)</code> returns <code>true</code>.
139     * <code>JSONObject.NULL.toString()</code> returns <code>"null"</code>.
140     */
141    public static final Object NULL = new Null();
142
143    /**
144     * Construct an empty JSONObject.
145     */
146    public JSONObject() {
147        this.map = new HashMap();
148    }
149
150    /**
151     * Construct a JSONObject from a subset of another JSONObject.
152     * An array of strings is used to identify the keys that should be copied.
153     * Missing keys are ignored.
154     * @param jo A JSONObject.
155     * @param names An array of strings.
156     */
157    public JSONObject(JSONObject jo, String[] names) {
158        this();
159        for (String name : names) {
160            try {
161                putOnce(name, jo.opt(name));
162            } catch (Exception ignore) {
163                // FIXME: It is wrong to ignore exceptions, this should be logged.
164            }
165        }
166    }
167
168    /**
169     * Construct a JSONObject from a JSONTokener.
170     * @param x A JSONTokener object containing the source string.
171     * @exception JSONException If there is a syntax error in the source string
172     *  or a duplicated key.
173     */
174    public JSONObject(JSONTokener x) throws JSONException {
175        this();
176        char c;
177        String key;
178
179        if (x.nextClean() != '{') {
180            throw x.syntaxError("A JSONObject text must begin with '{'");
181        }
182        for (;;) {
183            c = x.nextClean();
184            switch (c) {
185            case 0:
186                throw x.syntaxError("A JSONObject text must end with '}'");
187            case '}':
188                return;
189            default:
190                x.back();
191                key = x.nextValue().toString();
192            }
193
194            /*
195             * The key is followed by ':'. We will also tolerate '=' or '=>'.
196             */
197
198            c = x.nextClean();
199            if (c == '=') {
200                if (x.next() != '>') {
201                    x.back();
202                }
203            } else if (c != ':') {
204                throw x.syntaxError("Expected a ':' after a key");
205            }
206            putOnce(key, x.nextValue());
207
208            /*
209             * Pairs are separated by ','. We will also tolerate ';'.
210             */
211
212            switch (x.nextClean()) {
213            case ';':
214            case ',':
215                if (x.nextClean() == '}') {
216                    return;
217                }
218                x.back();
219                break;
220            case '}':
221                return;
222            default:
223                throw x.syntaxError("Expected a ',' or '}'");
224            }
225        }
226    }
227
228    /**
229     * Construct a JSONObject from a Map.
230     *
231     * @param map A map object that can be used to initialize the contents of
232     *  the JSONObject.
233     */
234    public JSONObject(Map map) {
235        this.map = new HashMap();
236        if (map != null) {
237            Iterator i = map.entrySet().iterator();
238            while (i.hasNext()) {
239                Map.Entry e = (Map.Entry) i.next();
240                map.put(e.getKey(), wrap(e.getValue()));
241            }
242        }
243    }
244
245    /**
246     * Construct a JSONObject from an Object using bean getters.
247     * It reflects on all of the public methods of the object.
248     * For each of the methods with no parameters and a name starting
249     * with <code>"get"</code> or <code>"is"</code> followed by an uppercase letter,
250     * the method is invoked, and a key and the value returned from the getter method
251     * are put into the new JSONObject.
252     *
253     * The key is formed by removing the <code>"get"</code> or <code>"is"</code> prefix.
254     * If the second remaining character is not upper case, then the first
255     * character is converted to lower case.
256     *
257     * For example, if an object has a method named <code>"getName"</code>, and
258     * if the result of calling <code>object.getName()</code> is <code>"Larry Fine"</code>,
259     * then the JSONObject will contain <code>"name": "Larry Fine"</code>.
260     *
261     * @param bean An object that has getter methods that should be used
262     * to make a JSONObject.
263     */
264    public JSONObject(Object bean) {
265        this();
266        populateMap(bean);
267    }
268
269    /**
270     * Construct a JSONObject from an Object, using reflection to find the
271     * public members. The resulting JSONObject's keys will be the strings
272     * from the names array, and the values will be the field values associated
273     * with those keys in the object. If a key is not found or not visible,
274     * then it will not be copied into the new JSONObject.
275     * @param object An object that has fields that should be used to make a
276     * JSONObject.
277     * @param names An array of strings, the names of the fields to be obtained
278     * from the object.
279     */
280    public JSONObject(Object object, String names[]) {
281        this();
282        Class c = object.getClass();
283        for (String name : names) {
284            try {
285                putOpt(name, c.getField(name).get(object));
286            } catch (Exception ignore) {
287            }
288        }
289    }
290
291    /**
292     * Construct a JSONObject from a source JSON text string.
293     * This is the most commonly used JSONObject constructor.
294     * @param source    A string beginning
295     *  with <code>{</code>&nbsp;<small>(left brace)</small> and ending
296     *  with <code>}</code>&nbsp;<small>(right brace)</small>.
297     * @exception JSONException If there is a syntax error in the source
298     *  string or a duplicated key.
299     */
300    public JSONObject(String source) throws JSONException {
301        this(new JSONTokener(source));
302    }
303
304    /**
305     * Accumulate values under a key. It is similar to the put method except
306     * that if there is already an object stored under the key then a
307     * JSONArray is stored under the key to hold all of the accumulated values.
308     * If there is already a JSONArray, then the new value is appended to it.
309     * In contrast, the put method replaces the previous value.
310     * @param key   A key string.
311     * @param value An object to be accumulated under the key.
312     * @return this.
313     * @exception JSONException If the value is an invalid number
314     *  or if the key is null.
315     */
316    public JSONObject accumulate(String key, Object value)
317            throws JSONException {
318        testValidity(value);
319        Object o = opt(key);
320        if (o == null) {
321            put(key, value instanceof JSONArray ? new JSONArray().put(value)
322                    : value);
323        } else if (o instanceof JSONArray) {
324            ((JSONArray) o).put(value);
325        } else {
326            put(key, new JSONArray().put(o).put(value));
327        }
328        return this;
329    }
330
331    /**
332     * Append values to the array under a key. If the key does not exist in the
333     * JSONObject, then the key is put in the JSONObject with its value being a
334     * JSONArray containing the value parameter. If the key was already
335     * associated with a JSONArray, then the value parameter is appended to it.
336     * @param key   A key string.
337     * @param value An object to be accumulated under the key.
338     * @return this.
339     * @exception JSONException If the key is null or if the current value
340     *  associated with the key is not a JSONArray.
341     */
342    public JSONObject append(String key, Object value) throws JSONException {
343        testValidity(value);
344        Object o = opt(key);
345        if (o == null) {
346            put(key, new JSONArray().put(value));
347        } else if (o instanceof JSONArray) {
348            put(key, ((JSONArray) o).put(value));
349        } else {
350            throw new JSONException(
351                    "JSONObject[" + key + "] is not a JSONArray.");
352        }
353        return this;
354    }
355
356    /**
357     * Produce a string from a double. The string "null" will be returned if
358     * the number is not finite.
359     * @param  d A double.
360     * @return A String.
361     */
362    static public String doubleToString(double d) {
363        if (Double.isInfinite(d) || Double.isNaN(d)) {
364            return "null";
365        }
366
367        // Shave off trailing zeros and decimal point, if possible.
368
369        String s = Double.toString(d);
370        if (s.indexOf('.') > 0 && s.indexOf('e') < 0 && s.indexOf('E') < 0) {
371            while (s.endsWith("0")) {
372                s = s.substring(0, s.length() - 1);
373            }
374            if (s.endsWith(".")) {
375                s = s.substring(0, s.length() - 1);
376            }
377        }
378        return s;
379    }
380
381    /**
382     * Get the value object associated with a key.
383     *
384     * @param key   A key string.
385     * @return      The object associated with the key.
386     * @exception   JSONException if the key is not found.
387     */
388    public Object get(String key) throws JSONException {
389        Object o = opt(key);
390        if (o == null) {
391            throw new JSONException(
392                    "JSONObject[" + quote(key) + "] not found.");
393        }
394        return o;
395    }
396
397    /**
398     * Get the boolean value associated with a key.
399     *
400     * @param key   A key string.
401     * @return      The truth.
402     * @exception   JSONException
403     *  if the value is not a Boolean or the String "true" or "false".
404     */
405    public boolean getBoolean(String key) throws JSONException {
406        Object o = get(key);
407        if (o.equals(Boolean.FALSE) || o instanceof String
408                && ((String) o).equalsIgnoreCase("false")) {
409            return false;
410        } else if (o.equals(Boolean.TRUE) || o instanceof String
411                && ((String) o).equalsIgnoreCase("true")) {
412            return true;
413        }
414        throw new JSONException(
415                "JSONObject[" + quote(key) + "] is not a Boolean.");
416    }
417
418    /**
419     * Get the double value associated with a key.
420     * @param key   A key string.
421     * @return      The numeric value.
422     * @exception JSONException if the key is not found or
423     *  if the value is not a Number object and cannot be converted to a number.
424     */
425    public double getDouble(String key) throws JSONException {
426        Object o = get(key);
427        try {
428            return o instanceof Number ? ((Number) o).doubleValue()
429                    : Double.valueOf((String) o).doubleValue();
430        } catch (Exception e) {
431            throw new JSONException(
432                    "JSONObject[" + quote(key) + "] is not a number.");
433        }
434    }
435
436    /**
437     * Get the int value associated with a key.
438     *
439     * @param key   A key string.
440     * @return      The integer value.
441     * @exception   JSONException if the key is not found or if the value cannot
442     *  be converted to an integer.
443     */
444    public int getInt(String key) throws JSONException {
445        Object o = get(key);
446        try {
447            return o instanceof Number ? ((Number) o).intValue()
448                    : Integer.parseInt((String) o);
449        } catch (Exception e) {
450            throw new JSONException(
451                    "JSONObject[" + quote(key) + "] is not an int.");
452        }
453    }
454
455    /**
456     * Get the JSONArray value associated with a key.
457     *
458     * @param key   A key string.
459     * @return      A JSONArray which is the value.
460     * @exception   JSONException if the key is not found or
461     *  if the value is not a JSONArray.
462     */
463    public JSONArray getJSONArray(String key) throws JSONException {
464        Object o = get(key);
465        if (o instanceof JSONArray) {
466            return (JSONArray) o;
467        }
468        throw new JSONException(
469                "JSONObject[" + quote(key) + "] is not a JSONArray.");
470    }
471
472    /**
473     * Get the JSONObject value associated with a key.
474     *
475     * @param key   A key string.
476     * @return      A JSONObject which is the value.
477     * @exception   JSONException if the key is not found or
478     *  if the value is not a JSONObject.
479     */
480    public JSONObject getJSONObject(String key) throws JSONException {
481        Object o = get(key);
482        if (o instanceof JSONObject) {
483            return (JSONObject) o;
484        }
485        throw new JSONException(
486                "JSONObject[" + quote(key) + "] is not a JSONObject.");
487    }
488
489    /**
490     * Get the long value associated with a key.
491     *
492     * @param key   A key string.
493     * @return      The long value.
494     * @exception   JSONException if the key is not found or if the value cannot
495     *  be converted to a long.
496     */
497    public long getLong(String key) throws JSONException {
498        Object o = get(key);
499        try {
500            return o instanceof Number ? ((Number) o).longValue()
501                    : Long.parseLong((String) o);
502        } catch (Exception e) {
503            throw new JSONException(
504                    "JSONObject[" + quote(key) + "] is not a long.");
505        }
506    }
507
508    /**
509     * Get an array of field names from a JSONObject.
510     *
511     * @return An array of field names, or null if there are no names.
512     */
513    public static String[] getNames(JSONObject jo) {
514        int length = jo.length();
515        if (length == 0) {
516            return null;
517        }
518        Iterator i = jo.keys();
519        String[] names = new String[length];
520        int j = 0;
521        while (i.hasNext()) {
522            names[j] = (String) i.next();
523            j += 1;
524        }
525        return names;
526    }
527
528    /**
529     * Get an array of field names from an Object.
530     *
531     * @return An array of field names, or null if there are no names.
532     */
533    public static String[] getNames(Object object) {
534        if (object == null) {
535            return null;
536        }
537        Class klass = object.getClass();
538        Field[] fields = klass.getFields();
539        int length = fields.length;
540        if (length == 0) {
541            return null;
542        }
543        String[] names = new String[length];
544        for (int i = 0; i < length; i += 1) {
545            names[i] = fields[i].getName();
546        }
547        return names;
548    }
549
550    /**
551     * Get the string associated with a key.
552     *
553     * @param key   A key string.
554     * @return      A string which is the value.
555     * @exception   JSONException if the key is not found.
556     */
557    public String getString(String key) throws JSONException {
558        return get(key).toString();
559    }
560
561    /**
562     * Determine if the JSONObject contains a specific key.
563     * @param key   A key string.
564     * @return      true if the key exists in the JSONObject.
565     */
566    public boolean has(String key) {
567        return this.map.containsKey(key);
568    }
569
570    /**
571     * Increment a property of a JSONObject. If there is no such property,
572     * create one with a value of 1. If there is such a property, and if
573     * it is an Integer, Long, Double, or Float, then add one to it.
574     * @param key  A key string.
575     * @return this.
576     * @exception JSONException If there is already a property with this name
577     * that is not an Integer, Long, Double, or Float.
578     */
579    public JSONObject increment(String key) throws JSONException {
580        Object value = opt(key);
581        if (value == null) {
582            put(key, 1);
583        } else {
584            if (value instanceof Integer) {
585                put(key, ((Integer) value).intValue() + 1);
586            } else if (value instanceof Long) {
587                put(key, ((Long) value).longValue() + 1);
588            } else if (value instanceof Double) {
589                put(key, ((Double) value).doubleValue() + 1);
590            } else if (value instanceof Float) {
591                put(key, ((Float) value).floatValue() + 1);
592            } else {
593                throw new JSONException("Unable to increment [" + key + "].");
594            }
595        }
596        return this;
597    }
598
599    /**
600     * Determine if the value associated with the key is null or if there is
601     *  no value.
602     * @param key   A key string.
603     * @return      true if there is no value associated with the key or if
604     *  the value is the JSONObject.NULL object.
605     */
606    public boolean isNull(String key) {
607        return JSONObject.NULL.equals(opt(key));
608    }
609
610    /**
611     * Get an enumeration of the keys of the JSONObject.
612     *
613     * @return An iterator of the keys.
614     */
615    public Iterator keys() {
616        return this.map.keySet().iterator();
617    }
618
619    /**
620     * Get the number of keys stored in the JSONObject.
621     *
622     * @return The number of keys in the JSONObject.
623     */
624    public int length() {
625        return this.map.size();
626    }
627
628    /**
629     * Produce a JSONArray containing the names of the elements of this
630     * JSONObject.
631     * @return A JSONArray containing the key strings, or null if the JSONObject
632     * is empty.
633     */
634    public JSONArray names() {
635        JSONArray ja = new JSONArray();
636        Iterator keys = keys();
637        while (keys.hasNext()) {
638            ja.put(keys.next());
639        }
640        return ja.length() == 0 ? null : ja;
641    }
642
643    /**
644     * Produce a string from a Number.
645     * @param  n A Number
646     * @return A String.
647     * @exception JSONException If n is a non-finite number.
648     */
649    static public String numberToString(Number n) throws JSONException {
650        if (n == null) {
651            throw new JSONException("Null pointer");
652        }
653        testValidity(n);
654
655        // Shave off trailing zeros and decimal point, if possible.
656
657        String s = n.toString();
658        if (s.indexOf('.') > 0 && s.indexOf('e') < 0 && s.indexOf('E') < 0) {
659            while (s.endsWith("0")) {
660                s = s.substring(0, s.length() - 1);
661            }
662            if (s.endsWith(".")) {
663                s = s.substring(0, s.length() - 1);
664            }
665        }
666        return s;
667    }
668
669    /**
670     * Get an optional value associated with a key.
671     * @param key   A key string.
672     * @return      An object which is the value, or null if there is no value.
673     */
674    public Object opt(String key) {
675        return key == null ? null : this.map.get(key);
676    }
677
678    /**
679     * Get an optional boolean associated with a key.
680     * It returns false if there is no such key, or if the value is not
681     * Boolean.TRUE or the String "true".
682     *
683     * @param key   A key string.
684     * @return      The truth.
685     */
686    public boolean optBoolean(String key) {
687        return optBoolean(key, false);
688    }
689
690    /**
691     * Get an optional boolean associated with a key.
692     * It returns the defaultValue if there is no such key, or if it is not
693     * a Boolean or the String "true" or "false" (case insensitive).
694     *
695     * @param key              A key string.
696     * @param defaultValue     The default.
697     * @return      The truth.
698     */
699    public boolean optBoolean(String key, boolean defaultValue) {
700        try {
701            return getBoolean(key);
702        } catch (Exception e) {
703            return defaultValue;
704        }
705    }
706
707    /**
708     * Get an optional double associated with a key,
709     * or NaN if there is no such key or if its value is not a number.
710     * If the value is a string, an attempt will be made to evaluate it as
711     * a number.
712     *
713     * @param key   A string which is the key.
714     * @return      An object which is the value.
715     */
716    public double optDouble(String key) {
717        return optDouble(key, Double.NaN);
718    }
719
720    /**
721     * Get an optional double associated with a key, or the
722     * defaultValue if there is no such key or if its value is not a number.
723     * If the value is a string, an attempt will be made to evaluate it as
724     * a number.
725     *
726     * @param key   A key string.
727     * @param defaultValue     The default.
728     * @return      An object which is the value.
729     */
730    public double optDouble(String key, double defaultValue) {
731        try {
732            Object o = opt(key);
733            return o instanceof Number ? ((Number) o).doubleValue()
734                    : new Double((String) o).doubleValue();
735        } catch (Exception e) {
736            return defaultValue;
737        }
738    }
739
740    /**
741     * Get an optional int value associated with a key,
742     * or zero if there is no such key or if the value is not a number.
743     * If the value is a string, an attempt will be made to evaluate it as
744     * a number.
745     *
746     * @param key   A key string.
747     * @return      An object which is the value.
748     */
749    public int optInt(String key) {
750        return optInt(key, 0);
751    }
752
753    /**
754     * Get an optional int value associated with a key,
755     * or the default if there is no such key or if the value is not a number.
756     * If the value is a string, an attempt will be made to evaluate it as
757     * a number.
758     *
759     * @param key   A key string.
760     * @param defaultValue     The default.
761     * @return      An object which is the value.
762     */
763    public int optInt(String key, int defaultValue) {
764        try {
765            return getInt(key);
766        } catch (Exception e) {
767            return defaultValue;
768        }
769    }
770
771    /**
772     * Get an optional JSONArray associated with a key.
773     * It returns null if there is no such key, or if its value is not a
774     * JSONArray.
775     *
776     * @param key   A key string.
777     * @return      A JSONArray which is the value.
778     */
779    public JSONArray optJSONArray(String key) {
780        Object o = opt(key);
781        return o instanceof JSONArray ? (JSONArray) o : null;
782    }
783
784    /**
785     * Get an optional JSONObject associated with a key.
786     * It returns null if there is no such key, or if its value is not a
787     * JSONObject.
788     *
789     * @param key   A key string.
790     * @return      A JSONObject which is the value.
791     */
792    public JSONObject optJSONObject(String key) {
793        Object o = opt(key);
794        return o instanceof JSONObject ? (JSONObject) o : null;
795    }
796
797    /**
798     * Get an optional long value associated with a key,
799     * or zero if there is no such key or if the value is not a number.
800     * If the value is a string, an attempt will be made to evaluate it as
801     * a number.
802     *
803     * @param key   A key string.
804     * @return      An object which is the value.
805     */
806    public long optLong(String key) {
807        return optLong(key, 0);
808    }
809
810    /**
811     * Get an optional long value associated with a key,
812     * or the default if there is no such key or if the value is not a number.
813     * If the value is a string, an attempt will be made to evaluate it as
814     * a number.
815     *
816     * @param key   A key string.
817     * @param defaultValue     The default.
818     * @return      An object which is the value.
819     */
820    public long optLong(String key, long defaultValue) {
821        try {
822            return getLong(key);
823        } catch (Exception e) {
824            return defaultValue;
825        }
826    }
827
828    /**
829     * Get an optional string associated with a key.
830     * It returns an empty string if there is no such key. If the value is not
831     * a string and is not null, then it is converted to a string.
832     *
833     * @param key   A key string.
834     * @return      A string which is the value.
835     */
836    public String optString(String key) {
837        return optString(key, "");
838    }
839
840    /**
841     * Get an optional string associated with a key.
842     * It returns the defaultValue if there is no such key.
843     *
844     * @param key   A key string.
845     * @param defaultValue     The default.
846     * @return      A string which is the value.
847     */
848    public String optString(String key, String defaultValue) {
849        Object o = opt(key);
850        return o != null ? o.toString() : defaultValue;
851    }
852
853    private void populateMap(Object bean) {
854        Class klass = bean.getClass();
855
856        // If klass is a System class then set includeSuperClass to false.
857
858        boolean includeSuperClass = klass.getClassLoader() != null;
859
860        Method[] methods = includeSuperClass ? klass.getMethods()
861                : klass.getDeclaredMethods();
862        for (Method method : methods) {
863            try {
864                if (Modifier.isPublic(method.getModifiers())) {
865                    String name = method.getName();
866                    String key = "";
867                    if (name.startsWith("get")) {
868                        if (name.equals("getClass")
869                                || name.equals("getDeclaringClass")) {
870                            key = "";
871                        } else {
872                            key = name.substring(3);
873                        }
874                    } else if (name.startsWith("is")) {
875                        key = name.substring(2);
876                    }
877                    if (key.length() > 0 && Character.isUpperCase(key.charAt(0))
878                            && method.getParameterTypes().length == 0) {
879                        if (key.length() == 1) {
880                            key = key.toLowerCase(Locale.getDefault());
881                        } else if (!Character.isUpperCase(key.charAt(1))) {
882                            key = key.substring(0, 1).toLowerCase(
883                                    Locale.getDefault()) + key.substring(1);
884                        }
885
886                        Object result = method.invoke(bean, (Object[]) null);
887
888                        map.put(key, wrap(result));
889                    }
890                }
891            } catch (Exception ignore) {
892            }
893        }
894    }
895
896    /**
897     * Put a key/boolean pair in the JSONObject.
898     *
899     * @param key   A key string.
900     * @param value A boolean which is the value.
901     * @return this.
902     * @exception JSONException If the key is null.
903     */
904    public JSONObject put(String key, boolean value) throws JSONException {
905        put(key, value ? Boolean.TRUE : Boolean.FALSE);
906        return this;
907    }
908
909    /**
910     * Put a key/value pair in the JSONObject, where the value will be a
911     * JSONArray which is produced from a Collection.
912     * @param key   A key string.
913     * @param value A Collection value.
914     * @return      this.
915     * @exception JSONException
916     */
917    public JSONObject put(String key, Collection value) throws JSONException {
918        put(key, new JSONArray(value));
919        return this;
920    }
921
922    /**
923     * Put a key/double pair in the JSONObject.
924     *
925     * @param key   A key string.
926     * @param value A double which is the value.
927     * @return this.
928     * @exception JSONException If the key is null or if the number is invalid.
929     */
930    public JSONObject put(String key, double value) throws JSONException {
931        put(key, new Double(value));
932        return this;
933    }
934
935    /**
936     * Put a key/int pair in the JSONObject.
937     *
938     * @param key   A key string.
939     * @param value An int which is the value.
940     * @return this.
941     * @exception JSONException If the key is null.
942     */
943    public JSONObject put(String key, int value) throws JSONException {
944        put(key, new Integer(value));
945        return this;
946    }
947
948    /**
949     * Put a key/long pair in the JSONObject.
950     *
951     * @param key   A key string.
952     * @param value A long which is the value.
953     * @return this.
954     * @exception JSONException If the key is null.
955     */
956    public JSONObject put(String key, long value) throws JSONException {
957        put(key, new Long(value));
958        return this;
959    }
960
961    /**
962     * Put a key/value pair in the JSONObject, where the value will be a
963     * JSONObject which is produced from a Map.
964     * @param key   A key string.
965     * @param value A Map value.
966     * @return      this.
967     * @exception JSONException
968     */
969    public JSONObject put(String key, Map value) throws JSONException {
970        put(key, new JSONObject(value));
971        return this;
972    }
973
974    /**
975     * Put a key/value pair in the JSONObject. If the value is null,
976     * then the key will be removed from the JSONObject if it is present.
977     * @param key   A key string.
978     * @param value An object which is the value. It should be of one of these
979     *  types: Boolean, Double, Integer, JSONArray, JSONObject, Long, String,
980     *  or the JSONObject.NULL object.
981     * @return this.
982     * @exception JSONException If the value is non-finite number
983     *  or if the key is null.
984     */
985    public JSONObject put(String key, Object value) throws JSONException {
986        if (key == null) {
987            throw new JSONException("Null key.");
988        }
989        if (value != null) {
990            testValidity(value);
991            this.map.put(key, value);
992        } else {
993            remove(key);
994        }
995        return this;
996    }
997
998    /**
999     * Put a key/value pair in the JSONObject, but only if the key and the
1000     * value are both non-null, and only if there is not already a member
1001     * with that name.
1002     * @param key
1003     * @param value
1004     * @return his.
1005     * @exception JSONException if the key is a duplicate
1006     */
1007    public JSONObject putOnce(String key, Object value) throws JSONException {
1008        if (key != null && value != null) {
1009            if (opt(key) != null) {
1010                throw new JSONException("Duplicate key \"" + key + "\"");
1011            }
1012            put(key, value);
1013        }
1014        return this;
1015    }
1016
1017    /**
1018     * Put a key/value pair in the JSONObject, but only if the
1019     * key and the value are both non-null.
1020     * @param key   A key string.
1021     * @param value An object which is the value. It should be of one of these
1022     *  types: Boolean, Double, Integer, JSONArray, JSONObject, Long, String,
1023     *  or the JSONObject.NULL object.
1024     * @return this.
1025     * @exception JSONException If the value is a non-finite number.
1026     */
1027    public JSONObject putOpt(String key, Object value) throws JSONException {
1028        if (key != null && value != null) {
1029            put(key, value);
1030        }
1031        return this;
1032    }
1033
1034    /**
1035     * Produce a string in double quotes with backslash sequences in all the
1036     * right places. A backslash will be inserted within &lt;/, allowing JSON
1037     * text to be delivered in HTML. In JSON text, a string cannot contain a
1038     * control character or an unescaped quote or backslash.
1039     * @param string A String
1040     * @return  A String correctly formatted for insertion in a JSON text.
1041     */
1042    public static String quote(String string) {
1043        if (string == null || string.length() == 0) {
1044            return "\"\"";
1045        }
1046
1047        char b;
1048        char c = 0;
1049        int i;
1050        int len = string.length();
1051        StringBuffer sb = new StringBuffer(len + 4);
1052        String t;
1053
1054        sb.append('"');
1055        for (i = 0; i < len; i += 1) {
1056            b = c;
1057            c = string.charAt(i);
1058            switch (c) {
1059            case '\\':
1060            case '"':
1061                sb.append('\\');
1062                sb.append(c);
1063                break;
1064            case '/':
1065                if (b == '<') {
1066                    sb.append('\\');
1067                }
1068                sb.append(c);
1069                break;
1070            case '\b':
1071                sb.append("\\b");
1072                break;
1073            case '\t':
1074                sb.append("\\t");
1075                break;
1076            case '\n':
1077                sb.append("\\n");
1078                break;
1079            case '\f':
1080                sb.append("\\f");
1081                break;
1082            case '\r':
1083                sb.append("\\r");
1084                break;
1085            default:
1086                if (c < ' ' || c >= '\u0080' && c < '\u00a0'
1087                        || c >= '\u2000' && c < '\u2100') {
1088                    t = "000" + Integer.toHexString(c);
1089                    sb.append("\\u" + t.substring(t.length() - 4));
1090                } else {
1091                    sb.append(c);
1092                }
1093            }
1094        }
1095        sb.append('"');
1096        return sb.toString();
1097    }
1098
1099    /**
1100     * Remove a name and its value, if present.
1101     * @param key The name to be removed.
1102     * @return The value that was associated with the name,
1103     * or null if there was no value.
1104     */
1105    public Object remove(String key) {
1106        return this.map.remove(key);
1107    }
1108
1109    /**
1110     * Get an enumeration of the keys of the JSONObject.
1111     * The keys will be sorted alphabetically.
1112     *
1113     * @return An iterator of the keys.
1114     */
1115    public Iterator sortedKeys() {
1116        return new TreeSet(this.map.keySet()).iterator();
1117    }
1118
1119    /**
1120     * Try to convert a string into a number, boolean, or null. If the string
1121     * can't be converted, return the string.
1122     * @param s A String.
1123     * @return A simple JSON value.
1124     */
1125    static public Object stringToValue(String s) {
1126        if (s.equals("")) {
1127            return s;
1128        }
1129        if (s.equalsIgnoreCase("true")) {
1130            return Boolean.TRUE;
1131        }
1132        if (s.equalsIgnoreCase("false")) {
1133            return Boolean.FALSE;
1134        }
1135        if (s.equalsIgnoreCase("null")) {
1136            return JSONObject.NULL;
1137        }
1138
1139        /*
1140         * If it might be a number, try converting it.
1141         * We support the non-standard 0x- convention.
1142         * If a number cannot be produced, then the value will just
1143         * be a string. Note that the 0x-, plus, and implied string
1144         * conventions are non-standard. A JSON parser may accept
1145         * non-JSON forms as long as it accepts all correct JSON forms.
1146         */
1147
1148        char b = s.charAt(0);
1149        if (b >= '0' && b <= '9' || b == '.' || b == '-' || b == '+') {
1150            if (b == '0' && s.length() > 2
1151                    && (s.charAt(1) == 'x' || s.charAt(1) == 'X')) {
1152                try {
1153                    return new Integer(Integer.parseInt(s.substring(2), 16));
1154                } catch (Exception ignore) {
1155                }
1156            }
1157            try {
1158                if (s.indexOf('.') > -1 || s.indexOf('e') > -1
1159                        || s.indexOf('E') > -1) {
1160                    return Double.valueOf(s);
1161                } else {
1162                    Long myLong = new Long(s);
1163                    if (myLong.longValue() == myLong.intValue()) {
1164                        return new Integer(myLong.intValue());
1165                    } else {
1166                        return myLong;
1167                    }
1168                }
1169            } catch (Exception ignore) {
1170            }
1171        }
1172        return s;
1173    }
1174
1175    /**
1176     * Throw an exception if the object is an NaN or infinite number.
1177     * @param o The object to test.
1178     * @exception JSONException If o is a non-finite number.
1179     */
1180    static void testValidity(Object o) throws JSONException {
1181        if (o != null) {
1182            if (o instanceof Double) {
1183                if (((Double) o).isInfinite() || ((Double) o).isNaN()) {
1184                    throw new JSONException(
1185                            "JSON does not allow non-finite numbers.");
1186                }
1187            } else if (o instanceof Float) {
1188                if (((Float) o).isInfinite() || ((Float) o).isNaN()) {
1189                    throw new JSONException(
1190                            "JSON does not allow non-finite numbers.");
1191                }
1192            }
1193        }
1194    }
1195
1196    /**
1197     * Produce a JSONArray containing the values of the members of this
1198     * JSONObject.
1199     * @param names A JSONArray containing a list of key strings. This
1200     * determines the sequence of the values in the result.
1201     * @return A JSONArray of values.
1202     * @exception JSONException If any of the values are non-finite numbers.
1203     */
1204    public JSONArray toJSONArray(JSONArray names) throws JSONException {
1205        if (names == null || names.length() == 0) {
1206            return null;
1207        }
1208        JSONArray ja = new JSONArray();
1209        for (int i = 0; i < names.length(); i += 1) {
1210            ja.put(this.opt(names.getString(i)));
1211        }
1212        return ja;
1213    }
1214
1215    /**
1216     * Make a JSON text of this JSONObject. For compactness, no whitespace
1217     * is added. If this would not result in a syntactically correct JSON text,
1218     * then null will be returned instead.
1219     * <p>
1220     * Warning: This method assumes that the data structure is acyclical.
1221     *
1222     * @return a printable, displayable, portable, transmittable
1223     *  representation of the object, beginning
1224     *  with <code>{</code>&nbsp;<small>(left brace)</small> and ending
1225     *  with <code>}</code>&nbsp;<small>(right brace)</small>.
1226     */
1227    @Override
1228    public String toString() {
1229        try {
1230            Iterator keys = keys();
1231            StringBuffer sb = new StringBuffer("{");
1232
1233            while (keys.hasNext()) {
1234                if (sb.length() > 1) {
1235                    sb.append(',');
1236                }
1237                Object o = keys.next();
1238                sb.append(quote(o.toString()));
1239                sb.append(':');
1240                sb.append(valueToString(this.map.get(o)));
1241            }
1242            sb.append('}');
1243            return sb.toString();
1244        } catch (Exception e) {
1245            return null;
1246        }
1247    }
1248
1249    /**
1250     * Make a prettyprinted JSON text of this JSONObject.
1251     * <p>
1252     * Warning: This method assumes that the data structure is acyclical.
1253     * @param indentFactor The number of spaces to add to each level of
1254     *  indentation.
1255     * @return a printable, displayable, portable, transmittable
1256     *  representation of the object, beginning
1257     *  with <code>{</code>&nbsp;<small>(left brace)</small> and ending
1258     *  with <code>}</code>&nbsp;<small>(right brace)</small>.
1259     * @exception JSONException If the object contains an invalid number.
1260     */
1261    public String toString(int indentFactor) throws JSONException {
1262        return toString(indentFactor, 0);
1263    }
1264
1265    /**
1266     * Make a prettyprinted JSON text of this JSONObject.
1267     * <p>
1268     * Warning: This method assumes that the data structure is acyclical.
1269     * @param indentFactor The number of spaces to add to each level of
1270     *  indentation.
1271     * @param indent The indentation of the top level.
1272     * @return a printable, displayable, transmittable
1273     *  representation of the object, beginning
1274     *  with <code>{</code>&nbsp;<small>(left brace)</small> and ending
1275     *  with <code>}</code>&nbsp;<small>(right brace)</small>.
1276     * @exception JSONException If the object contains an invalid number.
1277     */
1278    String toString(int indentFactor, int indent) throws JSONException {
1279        int j;
1280        int n = length();
1281        if (n == 0) {
1282            return "{}";
1283        }
1284        Iterator keys = sortedKeys();
1285        StringBuffer sb = new StringBuffer("{");
1286        int newindent = indent + indentFactor;
1287        Object o;
1288        if (n == 1) {
1289            o = keys.next();
1290            sb.append(quote(o.toString()));
1291            sb.append(": ");
1292            sb.append(valueToString(this.map.get(o), indentFactor, indent));
1293        } else {
1294            while (keys.hasNext()) {
1295                o = keys.next();
1296                if (sb.length() > 1) {
1297                    sb.append(",\n");
1298                } else {
1299                    sb.append('\n');
1300                }
1301                for (j = 0; j < newindent; j += 1) {
1302                    sb.append(' ');
1303                }
1304                sb.append(quote(o.toString()));
1305                sb.append(": ");
1306                sb.append(valueToString(this.map.get(o), indentFactor,
1307                        newindent));
1308            }
1309            if (sb.length() > 1) {
1310                sb.append('\n');
1311                for (j = 0; j < indent; j += 1) {
1312                    sb.append(' ');
1313                }
1314            }
1315        }
1316        sb.append('}');
1317        return sb.toString();
1318    }
1319
1320    /**
1321     * Make a JSON text of an Object value. If the object has an
1322     * value.toJSONString() method, then that method will be used to produce
1323     * the JSON text. The method is required to produce a strictly
1324     * conforming text. If the object does not contain a toJSONString
1325     * method (which is the most common case), then a text will be
1326     * produced by other means. If the value is an array or Collection,
1327     * then a JSONArray will be made from it and its toJSONString method
1328     * will be called. If the value is a MAP, then a JSONObject will be made
1329     * from it and its toJSONString method will be called. Otherwise, the
1330     * value's toString method will be called, and the result will be quoted.
1331     *
1332     * <p>
1333     * Warning: This method assumes that the data structure is acyclical.
1334     * @param value The value to be serialized.
1335     * @return a printable, displayable, transmittable
1336     *  representation of the object, beginning
1337     *  with <code>{</code>&nbsp;<small>(left brace)</small> and ending
1338     *  with <code>}</code>&nbsp;<small>(right brace)</small>.
1339     * @exception JSONException If the value is or contains an invalid number.
1340     */
1341    static String valueToString(Object value) throws JSONException {
1342        if (value == null || value.equals(null)) {
1343            return "null";
1344        }
1345        if (value instanceof JSONString) {
1346            Object o;
1347            try {
1348                o = ((JSONString) value).toJSONString();
1349            } catch (Exception e) {
1350                throw new JSONException(e);
1351            }
1352            if (o instanceof String) {
1353                return (String) o;
1354            }
1355            throw new JSONException("Bad value from toJSONString: " + o);
1356        }
1357        if (value instanceof Number) {
1358            return numberToString((Number) value);
1359        }
1360        if (value instanceof Boolean || value instanceof JSONObject
1361                || value instanceof JSONArray) {
1362            return value.toString();
1363        }
1364        if (value instanceof Map) {
1365            return new JSONObject((Map) value).toString();
1366        }
1367        if (value instanceof Collection) {
1368            return new JSONArray((Collection) value).toString();
1369        }
1370        if (value.getClass().isArray()) {
1371            return new JSONArray(value).toString();
1372        }
1373        return quote(value.toString());
1374    }
1375
1376    /**
1377     * Make a prettyprinted JSON text of an object value.
1378     * <p>
1379     * Warning: This method assumes that the data structure is acyclical.
1380     * @param value The value to be serialized.
1381     * @param indentFactor The number of spaces to add to each level of
1382     *  indentation.
1383     * @param indent The indentation of the top level.
1384     * @return a printable, displayable, transmittable
1385     *  representation of the object, beginning
1386     *  with <code>{</code>&nbsp;<small>(left brace)</small> and ending
1387     *  with <code>}</code>&nbsp;<small>(right brace)</small>.
1388     * @exception JSONException If the object contains an invalid number.
1389     */
1390    static String valueToString(Object value, int indentFactor, int indent)
1391            throws JSONException {
1392        if (value == null || value.equals(null)) {
1393            return "null";
1394        }
1395        try {
1396            if (value instanceof JSONString) {
1397                Object o = ((JSONString) value).toJSONString();
1398                if (o instanceof String) {
1399                    return (String) o;
1400                }
1401            }
1402        } catch (Exception ignore) {
1403        }
1404        if (value instanceof Number) {
1405            return numberToString((Number) value);
1406        }
1407        if (value instanceof Boolean) {
1408            return value.toString();
1409        }
1410        if (value instanceof JSONObject) {
1411            return ((JSONObject) value).toString(indentFactor, indent);
1412        }
1413        if (value instanceof JSONArray) {
1414            return ((JSONArray) value).toString(indentFactor, indent);
1415        }
1416        if (value instanceof Map) {
1417            return new JSONObject((Map) value).toString(indentFactor, indent);
1418        }
1419        if (value instanceof Collection) {
1420            return new JSONArray((Collection) value).toString(indentFactor,
1421                    indent);
1422        }
1423        if (value.getClass().isArray()) {
1424            return new JSONArray(value).toString(indentFactor, indent);
1425        }
1426        return quote(value.toString());
1427    }
1428
1429    /**
1430     * Wrap an object, if necessary. If the object is null, return the NULL
1431     * object. If it is an array or collection, wrap it in a JSONArray. If
1432     * it is a map, wrap it in a JSONObject. If it is a standard property
1433     * (Double, String, et al) then it is already wrapped. Otherwise, if it
1434     * comes from one of the java packages, turn it into a string. And if
1435     * it doesn't, try to wrap it in a JSONObject. If the wrapping fails,
1436     * then null is returned.
1437     *
1438     * @param object The object to wrap
1439     * @return The wrapped value
1440     */
1441    static Object wrap(Object object) {
1442        try {
1443            if (object == null) {
1444                return NULL;
1445            }
1446            if (object instanceof JSONObject || object instanceof JSONArray
1447                    || NULL.equals(object) || object instanceof JSONString
1448                    || object instanceof Byte || object instanceof Character
1449                    || object instanceof Short || object instanceof Integer
1450                    || object instanceof Long || object instanceof Boolean
1451                    || object instanceof Float || object instanceof Double
1452                    || object instanceof String) {
1453                return object;
1454            }
1455
1456            if (object instanceof Collection) {
1457                return new JSONArray((Collection) object);
1458            }
1459            if (object.getClass().isArray()) {
1460                return new JSONArray(object);
1461            }
1462            if (object instanceof Map) {
1463                return new JSONObject((Map) object);
1464            }
1465            Package objectPackage = object.getClass().getPackage();
1466            String objectPackageName = objectPackage != null
1467                    ? objectPackage.getName()
1468                    : "";
1469            if (objectPackageName.startsWith("java.")
1470                    || objectPackageName.startsWith("javax.")
1471                    || object.getClass().getClassLoader() == null) {
1472                return object.toString();
1473            }
1474            return new JSONObject(object);
1475        } catch (Exception exception) {
1476            return null;
1477        }
1478    }
1479
1480    /**
1481     * Write the contents of the JSONObject as JSON text to a writer.
1482     * For compactness, no whitespace is added.
1483     * <p>
1484     * Warning: This method assumes that the data structure is acyclical.
1485     *
1486     * @return The writer.
1487     * @exception JSONException
1488     */
1489    public Writer write(Writer writer) throws JSONException {
1490        try {
1491            boolean b = false;
1492            Iterator keys = keys();
1493            writer.write('{');
1494
1495            while (keys.hasNext()) {
1496                if (b) {
1497                    writer.write(',');
1498                }
1499                Object k = keys.next();
1500                writer.write(quote(k.toString()));
1501                writer.write(':');
1502                Object v = this.map.get(k);
1503                if (v instanceof JSONObject) {
1504                    ((JSONObject) v).write(writer);
1505                } else if (v instanceof JSONArray) {
1506                    ((JSONArray) v).write(writer);
1507                } else {
1508                    writer.write(valueToString(v));
1509                }
1510                b = true;
1511            }
1512            writer.write('}');
1513            return writer;
1514        } catch (IOException exception) {
1515            throw new JSONException(exception);
1516        }
1517    }
1518}