JAL-3619 fix up error messages and try to bail quietly if the viewer doesn’t open
[jalview.git] / src / org / json / JSONObject.java
1 package org.json;
2
3 import java.io.Closeable;
4
5 /*
6  * 
7  * Note: This file has been adapted for SwingJS by Bob Hanson hansonr@stolaf.edu 
8  * 
9  Copyright (c) 2002 JSON.org
10
11  Permission is hereby granted, free of charge, to any person obtaining a copy
12  of this software and associated documentation files (the "Software"), to deal
13  in the Software without restriction, including without limitation the rights
14  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15  copies of the Software, and to permit persons to whom the Software is
16  furnished to do so, subject to the following conditions:
17
18  The above copyright notice and this permission notice shall be included in all
19  copies or substantial portions of the Software.
20
21  The Software shall be used for Good, not Evil.
22
23  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29  SOFTWARE.
30  */
31
32 import java.io.IOException;
33 import java.io.StringWriter;
34 import java.io.Writer;
35 import java.lang.annotation.Annotation;
36 import java.lang.reflect.Field;
37 import java.lang.reflect.InvocationTargetException;
38 import java.lang.reflect.Method;
39 import java.lang.reflect.Modifier;
40 import java.math.BigDecimal;
41 import java.math.BigInteger;
42 import java.util.Collection;
43 import java.util.Enumeration;
44 import java.util.HashMap;
45 import java.util.Iterator;
46 import java.util.Locale;
47 import java.util.Map;
48 import java.util.Map.Entry;
49 import java.util.ResourceBundle;
50 import java.util.Set;
51
52 /**
53  * A JSONObject is an unordered collection of name/value pairs. Its external
54  * form is a string wrapped in curly braces with colons between the names and
55  * values, and commas between the values and names. The internal form is an
56  * object having <code>get</code> and <code>opt</code> methods for accessing the
57  * values by name, and <code>put</code> methods for adding or replacing values
58  * by name. The values can be any of these types: <code>Boolean</code>,
59  * <code>JSONArray</code>, <code>JSONObject</code>, <code>Number</code>,
60  * <code>String</code>, or the <code>JSONObject.NULL</code> object. A JSONObject
61  * constructor can be used to convert an external form JSON text into an
62  * internal form whose values can be retrieved with the <code>get</code> and
63  * <code>opt</code> methods, or to convert values into a JSON text using the
64  * <code>put</code> and <code>toString</code> methods. A <code>get</code> method
65  * returns a value if one can be found, and throws an exception if one cannot be
66  * found. An <code>opt</code> method returns a default value instead of throwing
67  * an exception, and so is useful for obtaining optional values.
68  * <p>
69  * The generic <code>get()</code> and <code>opt()</code> methods return an
70  * object, which you can cast or query for type. There are also typed
71  * <code>get</code> and <code>opt</code> methods that do type checking and type
72  * coercion for you. The opt methods differ from the get methods in that they do
73  * not throw. Instead, they return a specified value, such as null.
74  * <p>
75  * The <code>put</code> methods add or replace values in an object. For example,
76  *
77  * <pre>
78  * myString = new JSONObject().put(&quot;JSON&quot;, &quot;Hello, World!&quot;).toString();
79  * </pre>
80  *
81  * produces the string <code>{"JSON": "Hello, World"}</code>.
82  * <p>
83  * The texts produced by the <code>toString</code> methods strictly conform to
84  * the JSON syntax rules. The constructors are more forgiving in the texts they
85  * will accept:
86  * <ul>
87  * <li>An extra <code>,</code>&nbsp;<small>(comma)</small> may appear just
88  * before the closing brace.</li>
89  * <li>Strings may be quoted with <code>'</code>&nbsp;<small>(single
90  * quote)</small>.</li>
91  * <li>Strings do not need to be quoted at all if they do not begin with a quote
92  * or single quote, and if they do not contain leading or trailing spaces, and
93  * if they do not contain any of these characters:
94  * <code>{ } [ ] / \ : , #</code> and if they do not look like numbers and if
95  * they are not the reserved words <code>true</code>, <code>false</code>, or
96  * <code>null</code>.</li>
97  * </ul>
98  *
99  * @author JSON.org
100  * @version 2016-08-15
101  */
102 public class JSONObject {
103         /**
104          * JSONObject.NULL is equivalent to the value that JavaScript calls null, whilst
105          * Java's null is equivalent to the value that JavaScript calls undefined.
106          */
107         private static final class Null {
108
109                 /**
110                  * There is only intended to be a single instance of the NULL object, so the
111                  * clone method returns itself.
112                  *
113                  * @return NULL.
114                  */
115                 @Override
116                 protected final Object clone() {
117                         return this;
118                 }
119
120                 /**
121                  * A Null object is equal to the null value and to itself.
122                  *
123                  * @param object An object to test for nullness.
124                  * @return true if the object parameter is the JSONObject.NULL object or null.
125                  */
126                 @Override
127                 public boolean equals(Object object) {
128                         return object == null || object == this;
129                 }
130
131                 /**
132                  * A Null object is equal to the null value and to itself.
133                  *
134                  * @return always returns 0.
135                  */
136                 @Override
137                 public int hashCode() {
138                         return 0;
139                 }
140
141                 /**
142                  * Get the "null" string value.
143                  *
144                  * @return The string "null".
145                  */
146                 @Override
147                 public String toString() {
148                         return "null";
149                 }
150         }
151
152         /**
153          * The map where the JSONObject's properties are kept.
154          */
155         private final Map<String, Object> map;
156
157         /**
158          * It is sometimes more convenient and less ambiguous to have a
159          * <code>NULL</code> object than to use Java's <code>null</code> value.
160          * <code>JSONObject.NULL.equals(null)</code> returns <code>true</code>.
161          * <code>JSONObject.NULL.toString()</code> returns <code>"null"</code>.
162          */
163         public static final Object NULL = new Null();
164
165         /**
166          * Construct an empty JSONObject.
167          */
168         public JSONObject() {
169                 // HashMap is used on purpose to ensure that elements are unordered by
170                 // the specification.
171                 // JSON tends to be a portable transfer format to allows the container
172                 // implementations to rearrange their items for a faster element
173                 // retrieval based on associative access.
174                 // Therefore, an implementation mustn't rely on the order of the item.
175                 this.map = new HashMap<String, Object>();
176         }
177
178         /**
179          * Construct a JSONObject from a subset of another JSONObject. An array of
180          * strings is used to identify the keys that should be copied. Missing keys are
181          * ignored.
182          *
183          * @param jo    A JSONObject.
184          * @param names An array of strings.
185          */
186         public JSONObject(JSONObject jo, String[] names) {
187                 this(names.length);
188                 for (int i = 0; i < names.length; i += 1) {
189                         try {
190                                 this.putOnce(names[i], jo.opt(names[i]));
191                         } catch (Exception ignore) {
192                         }
193                 }
194         }
195
196         /**
197          * Construct a JSONObject from a JSONTokener.
198          *
199          * @param x A JSONTokener object containing the source string.
200          * @throws JSONException If there is a syntax error in the source string or a
201          *                       duplicated key.
202          */
203         public JSONObject(JSONTokener x) throws JSONException {
204                 this();
205                 char c;
206                 String key;
207
208                 if (x.nextClean() != '{') {
209                         throw x.syntaxError("A JSONObject text must begin with '{'");
210                 }
211                 for (;;) {
212                         c = x.nextClean();
213                         switch (c) {
214                         case 0:
215                                 throw x.syntaxError("A JSONObject text must end with '}'");
216                         case '}':
217                                 return;
218                         default:
219                                 x.back();
220                                 key = x.nextValue().toString();
221                         }
222
223                         // The key is followed by ':'.
224
225                         c = x.nextClean();
226                         if (c != ':') {
227                                 throw x.syntaxError("Expected a ':' after a key");
228                         }
229
230                         // Use syntaxError(..) to include error location
231
232                         if (key != null) {
233                                 // Check if key exists
234                                 if (this.opt(key) != null) {
235                                         // key already exists
236                                         throw x.syntaxError("Duplicate key \"" + key + "\"");
237                                 }
238                                 // Only add value if non-null
239                                 Object value = x.nextValue();
240                                 if (value != null) {
241                                         this.put(key, value);
242                                 }
243                         }
244
245                         // Pairs are separated by ','.
246
247                         switch (x.nextClean()) {
248                         case ';':
249                         case ',':
250                                 if (x.nextClean() == '}') {
251                                         return;
252                                 }
253                                 x.back();
254                                 break;
255                         case '}':
256                                 return;
257                         default:
258                                 throw x.syntaxError("Expected a ',' or '}'");
259                         }
260                 }
261         }
262
263         /**
264          * Construct a JSONObject from a Map.
265          *
266          * @param m A map object that can be used to initialize the contents of the
267          *          JSONObject.
268          * @throws JSONException        If a value in the map is non-finite number.
269          * @throws NullPointerException If a key in the map is <code>null</code>
270          */
271         public JSONObject(Map<?, ?> m) {
272                 if (m == null) {
273                         this.map = new HashMap<String, Object>();
274                 } else {
275                         this.map = new HashMap<String, Object>(m.size());
276                         for (final Entry<?, ?> e : m.entrySet()) {
277                                 if (e.getKey() == null) {
278                                         throw new NullPointerException("Null key.");
279                                 }
280                                 final Object value = e.getValue();
281                                 if (value != null) {
282                                         this.map.put(String.valueOf(e.getKey()), wrap(value));
283                                 }
284                         }
285                 }
286         }
287
288         /**
289          * Construct a JSONObject from an Object using bean getters. It reflects on all
290          * of the public methods of the object. For each of the methods with no
291          * parameters and a name starting with <code>"get"</code> or <code>"is"</code>
292          * followed by an uppercase letter, the method is invoked, and a key and the
293          * value returned from the getter method are put into the new JSONObject.
294          * <p>
295          * The key is formed by removing the <code>"get"</code> or <code>"is"</code>
296          * prefix. If the second remaining character is not upper case, then the first
297          * character is converted to lower case.
298          * <p>
299          * Methods that are <code>static</code>, return <code>void</code>, have
300          * parameters, or are "bridge" methods, are ignored.
301          * <p>
302          * For example, if an object has a method named <code>"getName"</code>, and if
303          * the result of calling <code>object.getName()</code> is
304          * <code>"Larry Fine"</code>, then the JSONObject will contain
305          * <code>"name": "Larry Fine"</code>.
306          * <p>
307          * The {@link JSONPropertyName} annotation can be used on a bean getter to
308          * override key name used in the JSONObject. For example, using the object above
309          * with the <code>getName</code> method, if we annotated it with:
310          * 
311          * <pre>
312          * &#64;JSONPropertyName("FullName")
313          * public String getName() {
314          *      return this.name;
315          * }
316          * </pre>
317          * 
318          * The resulting JSON object would contain <code>"FullName": "Larry Fine"</code>
319          * <p>
320          * Similarly, the {@link JSONPropertyName} annotation can be used on non-
321          * <code>get</code> and <code>is</code> methods. We can also override key name
322          * used in the JSONObject as seen below even though the field would normally be
323          * ignored:
324          * 
325          * <pre>
326          * &#64;JSONPropertyName("FullName")
327          * public String fullName() {
328          *      return this.name;
329          * }
330          * </pre>
331          * 
332          * The resulting JSON object would contain <code>"FullName": "Larry Fine"</code>
333          * <p>
334          * The {@link JSONPropertyIgnore} annotation can be used to force the bean
335          * property to not be serialized into JSON. If both {@link JSONPropertyIgnore}
336          * and {@link JSONPropertyName} are defined on the same method, a depth
337          * comparison is performed and the one closest to the concrete class being
338          * serialized is used. If both annotations are at the same level, then the
339          * {@link JSONPropertyIgnore} annotation takes precedent and the field is not
340          * serialized. For example, the following declaration would prevent the
341          * <code>getName</code> method from being serialized:
342          * 
343          * <pre>
344          * &#64;JSONPropertyName("FullName")
345          * &#64;JSONPropertyIgnore
346          * public String getName() {
347          *      return this.name;
348          * }
349          * </pre>
350          * <p>
351          * 
352          * @param bean An object that has getter methods that should be used to make a
353          *             JSONObject.
354          */
355         public JSONObject(Object bean) {
356                 this();
357                 this.populateMap(bean);
358         }
359
360         /**
361          * Construct a JSONObject from an Object, using reflection to find the public
362          * members. The resulting JSONObject's keys will be the strings from the names
363          * array, and the values will be the field values associated with those keys in
364          * the object. If a key is not found or not visible, then it will not be copied
365          * into the new JSONObject.
366          *
367          * @param object An object that has fields that should be used to make a
368          *               JSONObject.
369          * @param names  An array of strings, the names of the fields to be obtained
370          *               from the object.
371          */
372         public JSONObject(Object object, String names[]) {
373                 this(names.length);
374                 Class<?> c = object.getClass();
375                 for (int i = 0; i < names.length; i += 1) {
376                         String name = names[i];
377                         try {
378                                 this.putOpt(name, c.getField(name).get(object));
379                         } catch (Exception ignore) {
380                         }
381                 }
382         }
383
384         /**
385          * Construct a JSONObject from a source JSON text string. This is the most
386          * commonly used JSONObject constructor.
387          *
388          * @param source A string beginning with <code>{</code>&nbsp;<small>(left
389          *               brace)</small> and ending with <code>}</code>
390          *               &nbsp;<small>(right brace)</small>.
391          * @exception JSONException If there is a syntax error in the source string or a
392          *                          duplicated key.
393          */
394         public JSONObject(String source) throws JSONException {
395                 this(new JSONTokener(source));
396         }
397
398         /**
399          * Construct a JSONObject from a ResourceBundle.
400          *
401          * @param baseName The ResourceBundle base name.
402          * @param locale   The Locale to load the ResourceBundle for.
403          * @throws JSONException If any JSONExceptions are detected.
404          */
405         public JSONObject(String baseName, Locale locale) throws JSONException {
406                 this();
407                 ResourceBundle bundle = ResourceBundle.getBundle(baseName, locale,
408                                 Thread.currentThread().getContextClassLoader());
409
410 // Iterate through the keys in the bundle.
411
412                 Enumeration<String> keys = bundle.getKeys();
413                 while (keys.hasMoreElements()) {
414                         Object key = keys.nextElement();
415                         if (key != null) {
416
417 // Go through the path, ensuring that there is a nested JSONObject for each
418 // segment except the last. Add the value using the last segment's name into
419 // the deepest nested JSONObject.
420
421                                 String[] path = ((String) key).split("\\.");
422                                 int last = path.length - 1;
423                                 JSONObject target = this;
424                                 for (int i = 0; i < last; i += 1) {
425                                         String segment = path[i];
426                                         JSONObject nextTarget = target.optJSONObject(segment);
427                                         if (nextTarget == null) {
428                                                 nextTarget = new JSONObject();
429                                                 target.put(segment, nextTarget);
430                                         }
431                                         target = nextTarget;
432                                 }
433                                 target.put(path[last], bundle.getString((String) key));
434                         }
435                 }
436         }
437
438         /**
439          * Constructor to specify an initial capacity of the internal map. Useful for
440          * library internal calls where we know, or at least can best guess, how big
441          * this JSONObject will be.
442          * 
443          * @param initialCapacity initial capacity of the internal map.
444          */
445         protected JSONObject(int initialCapacity) {
446                 this.map = new HashMap<String, Object>(initialCapacity);
447         }
448
449         /**
450          * Accumulate values under a key. It is similar to the put method except that if
451          * there is already an object stored under the key then a JSONArray is stored
452          * under the key to hold all of the accumulated values. If there is already a
453          * JSONArray, then the new value is appended to it. In contrast, the put method
454          * replaces the previous value.
455          *
456          * If only one value is accumulated that is not a JSONArray, then the result
457          * will be the same as using put. But if multiple values are accumulated, then
458          * the result will be like append.
459          *
460          * @param key   A key string.
461          * @param value An object to be accumulated under the key.
462          * @return this.
463          * @throws JSONException        If the value is non-finite number.
464          * @throws NullPointerException If the key is <code>null</code>.
465          */
466         public JSONObject accumulate(String key, Object value) throws JSONException {
467                 testValidity(value);
468                 Object object = this.opt(key);
469                 if (object == null) {
470                         this.put(key, value instanceof JSONArray ? new JSONArray().put(value) : value);
471                 } else if (object instanceof JSONArray) {
472                         ((JSONArray) object).put(value);
473                 } else {
474                         this.put(key, new JSONArray().put(object).put(value));
475                 }
476                 return this;
477         }
478
479         /**
480          * Append values to the array under a key. If the key does not exist in the
481          * JSONObject, then the key is put in the JSONObject with its value being a
482          * JSONArray containing the value parameter. If the key was already associated
483          * with a JSONArray, then the value parameter is appended to it.
484          *
485          * @param key   A key string.
486          * @param value An object to be accumulated under the key.
487          * @return this.
488          * @throws JSONException        If the value is non-finite number or if the
489          *                              current value associated with the key is not a
490          *                              JSONArray.
491          * @throws NullPointerException If the key is <code>null</code>.
492          */
493         public JSONObject append(String key, Object value) throws JSONException {
494                 testValidity(value);
495                 Object object = this.opt(key);
496                 if (object == null) {
497                         this.put(key, new JSONArray().put(value));
498                 } else if (object instanceof JSONArray) {
499                         this.put(key, ((JSONArray) object).put(value));
500                 } else {
501                         throw new JSONException("JSONObject[" + key + "] is not a JSONArray.");
502                 }
503                 return this;
504         }
505
506         /**
507          * Produce a string from a double. The string "null" will be returned if the
508          * number is not finite.
509          *
510          * @param d A double.
511          * @return A String.
512          */
513         public static String doubleToString(double d) {
514                 if (Double.isInfinite(d) || Double.isNaN(d)) {
515                         return "null";
516                 }
517
518 // Shave off trailing zeros and decimal point, if possible.
519
520                 String string = Double.toString(d);
521                 if (string.indexOf('.') > 0 && string.indexOf('e') < 0 && string.indexOf('E') < 0) {
522                         while (string.endsWith("0")) {
523                                 string = string.substring(0, string.length() - 1);
524                         }
525                         if (string.endsWith(".")) {
526                                 string = string.substring(0, string.length() - 1);
527                         }
528                 }
529                 return string;
530         }
531
532         /**
533          * Get the value object associated with a key.
534          *
535          * @param key A key string.
536          * @return The object associated with the key.
537          * @throws JSONException if the key is not found.
538          */
539         public Object get(String key) throws JSONException {
540                 if (key == null) {
541                         throw new JSONException("Null key.");
542                 }
543                 Object object = this.opt(key);
544                 if (object == null) {
545                         throw new JSONException("JSONObject[" + quote(key) + "] not found.");
546                 }
547                 return object;
548         }
549
550         /**
551          * Get the enum value associated with a key.
552          * 
553          * @param clazz The type of enum to retrieve.
554          * @param key   A key string.
555          * @return The enum value associated with the key
556          * @throws JSONException if the key is not found or if the value cannot be
557          *                       converted to an enum.
558          */
559         public <E extends Enum<E>> E getEnum(Class<E> clazz, String key) throws JSONException {
560                 E val = optEnum(clazz, key);
561                 if (val == null) {
562                         // JSONException should really take a throwable argument.
563                         // If it did, I would re-implement this with the Enum.valueOf
564                         // method and place any thrown exception in the JSONException
565                         throw new JSONException(
566                                         "JSONObject[" + quote(key) + "] is not an enum of type " + quote(clazz.getSimpleName()) + ".");
567                 }
568                 return val;
569         }
570
571         /**
572          * Get the boolean value associated with a key.
573          *
574          * @param key A key string.
575          * @return The truth.
576          * @throws JSONException if the value is not a Boolean or the String "true" or
577          *                       "false".
578          */
579         public boolean getBoolean(String key) throws JSONException {
580                 Object object = this.get(key);
581                 if (object.equals(Boolean.FALSE) || (object instanceof String && ((String) object).equalsIgnoreCase("false"))) {
582                         return false;
583                 } else if (object.equals(Boolean.TRUE)
584                                 || (object instanceof String && ((String) object).equalsIgnoreCase("true"))) {
585                         return true;
586                 }
587                 throw new JSONException("JSONObject[" + quote(key) + "] is not a Boolean.");
588         }
589
590         /**
591          * Get the BigInteger value associated with a key.
592          *
593          * @param key A key string.
594          * @return The numeric value.
595          * @throws JSONException if the key is not found or if the value cannot be
596          *                       converted to BigInteger.
597          */
598         public BigInteger getBigInteger(String key) throws JSONException {
599                 Object object = this.get(key);
600                 try {
601                         return new BigInteger(object.toString());
602                 } catch (Exception e) {
603                         throw new JSONException("JSONObject[" + quote(key) + "] could not be converted to BigInteger.", e);
604                 }
605         }
606
607         /**
608          * Get the BigDecimal value associated with a key.
609          *
610          * @param key A key string.
611          * @return The numeric value.
612          * @throws JSONException if the key is not found or if the value cannot be
613          *                       converted to BigDecimal.
614          */
615         public BigDecimal getBigDecimal(String key) throws JSONException {
616                 Object object = this.get(key);
617                 if (object instanceof BigDecimal) {
618                         return (BigDecimal) object;
619                 }
620                 try {
621                         return new BigDecimal(object.toString());
622                 } catch (Exception e) {
623                         throw new JSONException("JSONObject[" + quote(key) + "] could not be converted to BigDecimal.", e);
624                 }
625         }
626
627         /**
628          * Get the double value associated with a key.
629          *
630          * @param key A key string.
631          * @return The numeric value.
632          * @throws JSONException if the key is not found or if the value is not a Number
633          *                       object and cannot be converted to a number.
634          */
635         public double getDouble(String key) throws JSONException {
636                 Object object = this.get(key);
637                 try {
638                         return object instanceof Number ? ((Number) object).doubleValue() : Double.parseDouble(object.toString());
639                 } catch (Exception e) {
640                         throw new JSONException("JSONObject[" + quote(key) + "] is not a number.", e);
641                 }
642         }
643
644         /**
645          * Get the float value associated with a key.
646          *
647          * @param key A key string.
648          * @return The numeric value.
649          * @throws JSONException if the key is not found or if the value is not a Number
650          *                       object and cannot be converted to a number.
651          */
652         public float getFloat(String key) throws JSONException {
653                 Object object = this.get(key);
654                 try {
655                         return object instanceof Number ? ((Number) object).floatValue() : Float.parseFloat(object.toString());
656                 } catch (Exception e) {
657                         throw new JSONException("JSONObject[" + quote(key) + "] is not a number.", e);
658                 }
659         }
660
661         /**
662          * Get the Number value associated with a key.
663          *
664          * @param key A key string.
665          * @return The numeric value.
666          * @throws JSONException if the key is not found or if the value is not a Number
667          *                       object and cannot be converted to a number.
668          */
669         public Number getNumber(String key) throws JSONException {
670                 Object object = this.get(key);
671                 try {
672                         if (object instanceof Number) {
673                                 return (Number) object;
674                         }
675                         return stringToNumber(object.toString());
676                 } catch (Exception e) {
677                         throw new JSONException("JSONObject[" + quote(key) + "] is not a number.", e);
678                 }
679         }
680
681         /**
682          * Get the int value associated with a key.
683          *
684          * @param key A key string.
685          * @return The integer value.
686          * @throws JSONException if the key is not found or if the value cannot be
687          *                       converted to an integer.
688          */
689         public int getInt(String key) throws JSONException {
690                 Object object = this.get(key);
691                 try {
692                         return object instanceof Number ? ((Number) object).intValue() : Integer.parseInt((String) object);
693                 } catch (Exception e) {
694                         throw new JSONException("JSONObject[" + quote(key) + "] is not an int.", e);
695                 }
696         }
697
698         /**
699          * Get the JSONArray value associated with a key.
700          *
701          * @param key A key string.
702          * @return A JSONArray which is the value.
703          * @throws JSONException if the key is not found or if the value is not a
704          *                       JSONArray.
705          */
706         public JSONArray getJSONArray(String key) throws JSONException {
707                 Object object = this.get(key);
708                 if (object instanceof JSONArray) {
709                         return (JSONArray) object;
710                 }
711                 throw new JSONException("JSONObject[" + quote(key) + "] is not a JSONArray.");
712         }
713
714         /**
715          * Get the JSONObject value associated with a key.
716          *
717          * @param key A key string.
718          * @return A JSONObject which is the value.
719          * @throws JSONException if the key is not found or if the value is not a
720          *                       JSONObject.
721          */
722         public JSONObject getJSONObject(String key) throws JSONException {
723                 Object object = this.get(key);
724                 if (object instanceof JSONObject) {
725                         return (JSONObject) object;
726                 }
727                 throw new JSONException("JSONObject[" + quote(key) + "] is not a JSONObject.");
728         }
729
730         /**
731          * Get the long value associated with a key.
732          *
733          * @param key A key string.
734          * @return The long value.
735          * @throws JSONException if the key is not found or if the value cannot be
736          *                       converted to a long.
737          */
738         public long getLong(String key) throws JSONException {
739                 Object object = this.get(key);
740                 try {
741                         return object instanceof Number ? ((Number) object).longValue() : Long.parseLong((String) object);
742                 } catch (Exception e) {
743                         throw new JSONException("JSONObject[" + quote(key) + "] is not a long.", e);
744                 }
745         }
746
747         /**
748          * Get an array of field names from a JSONObject.
749          *
750          * @return An array of field names, or null if there are no names.
751          */
752         public static String[] getNames(JSONObject jo) {
753                 if (jo.isEmpty()) {
754                         return null;
755                 }
756                 return jo.keySet().toArray(new String[jo.length()]);
757         }
758
759         /**
760          * Get an array of field names from an Object.
761          *
762          * @return An array of field names, or null if there are no names.
763          */
764         public static String[] getNames(Object object) {
765                 if (object == null) {
766                         return null;
767                 }
768                 Class<?> klass = object.getClass();
769                 Field[] fields = klass.getFields();
770                 int length = fields.length;
771                 if (length == 0) {
772                         return null;
773                 }
774                 String[] names = new String[length];
775                 for (int i = 0; i < length; i += 1) {
776                         names[i] = fields[i].getName();
777                 }
778                 return names;
779         }
780
781         /**
782          * Get the string associated with a key.
783          *
784          * @param key A key string.
785          * @return A string which is the value.
786          * @throws JSONException if there is no string value for the key.
787          */
788         public String getString(String key) throws JSONException {
789                 Object object = this.get(key);
790                 if (object instanceof String) {
791                         return (String) object;
792                 }
793                 throw new JSONException("JSONObject[" + quote(key) + "] not a string.");
794         }
795
796         /**
797          * Determine if the JSONObject contains a specific key.
798          *
799          * @param key A key string.
800          * @return true if the key exists in the JSONObject.
801          */
802         public boolean has(String key) {
803                 return this.map.containsKey(key);
804         }
805
806         /**
807          * Increment a property of a JSONObject. If there is no such property, create
808          * one with a value of 1. If there is such a property, and if it is an Integer,
809          * Long, Double, or Float, then add one to it.
810          *
811          * @param key A key string.
812          * @return this.
813          * @throws JSONException If there is already a property with this name that is
814          *                       not an Integer, Long, Double, or Float.
815          */
816         public JSONObject increment(String key) throws JSONException {
817                 Object value = this.opt(key);
818                 if (value == null) {
819                         this.put(key, 1);
820                 } else if (value instanceof BigInteger) {
821                         this.put(key, ((BigInteger) value).add(BigInteger.ONE));
822                 } else if (value instanceof BigDecimal) {
823                         this.put(key, ((BigDecimal) value).add(BigDecimal.ONE));
824                 } else if (value instanceof Integer) {
825                         this.put(key, ((Integer) value).intValue() + 1);
826                 } else if (value instanceof Long) {
827                         this.put(key, ((Long) value).longValue() + 1L);
828                 } else if (value instanceof Double) {
829                         this.put(key, ((Double) value).doubleValue() + 1.0d);
830                 } else if (value instanceof Float) {
831                         this.put(key, ((Float) value).floatValue() + 1.0f);
832                 } else {
833                         throw new JSONException("Unable to increment [" + quote(key) + "].");
834                 }
835                 return this;
836         }
837
838         /**
839          * Determine if the value associated with the key is <code>null</code> or if
840          * there is no value.
841          *
842          * @param key A key string.
843          * @return true if there is no value associated with the key or if the value is
844          *         the JSONObject.NULL object.
845          */
846         public boolean isNull(String key) {
847                 return JSONObject.NULL.equals(this.opt(key));
848         }
849
850         /**
851          * Get an enumeration of the keys of the JSONObject. Modifying this key Set will
852          * also modify the JSONObject. Use with caution.
853          *
854          * @see Set#iterator()
855          * 
856          * @return An iterator of the keys.
857          */
858         public Iterator<String> keys() {
859                 return this.keySet().iterator();
860         }
861
862         /**
863          * Get a set of keys of the JSONObject. Modifying this key Set will also modify
864          * the JSONObject. Use with caution.
865          *
866          * @see Map#keySet()
867          *
868          * @return A keySet.
869          */
870         public Set<String> keySet() {
871                 return this.map.keySet();
872         }
873
874         /**
875          * Get a set of entries of the JSONObject. These are raw values and may not
876          * match what is returned by the JSONObject get* and opt* functions. Modifying
877          * the returned EntrySet or the Entry objects contained therein will modify the
878          * backing JSONObject. This does not return a clone or a read-only view.
879          * 
880          * Use with caution.
881          *
882          * @see Map#entrySet()
883          *
884          * @return An Entry Set
885          */
886         protected Set<Entry<String, Object>> entrySet() {
887                 return this.map.entrySet();
888         }
889
890         /**
891          * Get the number of keys stored in the JSONObject.
892          *
893          * @return The number of keys in the JSONObject.
894          */
895         public int length() {
896                 return this.map.size();
897         }
898
899         /**
900          * Check if JSONObject is empty.
901          *
902          * @return true if JSONObject is empty, otherwise false.
903          */
904         public boolean isEmpty() {
905                 return map.isEmpty();
906         }
907
908         /**
909          * Produce a JSONArray containing the names of the elements of this JSONObject.
910          *
911          * @return A JSONArray containing the key strings, or null if the JSONObject is
912          *         empty.
913          */
914         public JSONArray names() {
915                 if (this.map.isEmpty()) {
916                         return null;
917                 }
918                 return new JSONArray(this.map.keySet());
919         }
920
921         /**
922          * Produce a string from a Number.
923          *
924          * @param number A Number
925          * @return A String.
926          * @throws JSONException If n is a non-finite number.
927          */
928         public static String numberToString(Number number) throws JSONException {
929                 if (number == null) {
930                         throw new JSONException("Null pointer");
931                 }
932                 testValidity(number);
933
934                 // Shave off trailing zeros and decimal point, if possible.
935
936                 String string = number.toString();
937                 if (string.indexOf('.') > 0 && string.indexOf('e') < 0 && string.indexOf('E') < 0) {
938                         while (string.endsWith("0")) {
939                                 string = string.substring(0, string.length() - 1);
940                         }
941                         if (string.endsWith(".")) {
942                                 string = string.substring(0, string.length() - 1);
943                         }
944                 }
945                 return string;
946         }
947
948         /**
949          * Get an optional value associated with a key.
950          *
951          * @param key A key string.
952          * @return An object which is the value, or null if there is no value.
953          */
954         public Object opt(String key) {
955                 return key == null ? null : this.map.get(key);
956         }
957
958         /**
959          * Get the enum value associated with a key.
960          * 
961          * @param clazz The type of enum to retrieve.
962          * @param key   A key string.
963          * @return The enum value associated with the key or null if not found
964          */
965         public <E extends Enum<E>> E optEnum(Class<E> clazz, String key) {
966                 return this.optEnum(clazz, key, null);
967         }
968
969         /**
970          * Get the enum value associated with a key.
971          * 
972          * @param clazz        The type of enum to retrieve.
973          * @param key          A key string.
974          * @param defaultValue The default in case the value is not found
975          * @return The enum value associated with the key or defaultValue if the value
976          *         is not found or cannot be assigned to <code>clazz</code>
977          */
978         public <E extends Enum<E>> E optEnum(Class<E> clazz, String key, E defaultValue) {
979                 try {
980                         Object val = this.opt(key);
981                         if (NULL.equals(val)) {
982                                 return defaultValue;
983                         }
984                         if (clazz.isAssignableFrom(val.getClass())) {
985                                 // we just checked it!
986                                 @SuppressWarnings("unchecked")
987                                 E myE = (E) val;
988                                 return myE;
989                         }
990                         return Enum.valueOf(clazz, val.toString());
991                 } catch (IllegalArgumentException e) {
992                         return defaultValue;
993                 } catch (NullPointerException e) {
994                         return defaultValue;
995                 }
996         }
997
998         /**
999          * Get an optional boolean associated with a key. It returns false if there is
1000          * no such key, or if the value is not Boolean.TRUE or the String "true".
1001          *
1002          * @param key A key string.
1003          * @return The truth.
1004          */
1005         public boolean optBoolean(String key) {
1006                 return this.optBoolean(key, false);
1007         }
1008
1009         /**
1010          * Get an optional boolean associated with a key. It returns the defaultValue if
1011          * there is no such key, or if it is not a Boolean or the String "true" or
1012          * "false" (case insensitive).
1013          *
1014          * @param key          A key string.
1015          * @param defaultValue The default.
1016          * @return The truth.
1017          */
1018         public boolean optBoolean(String key, boolean defaultValue) {
1019                 Object val = this.opt(key);
1020                 if (NULL.equals(val)) {
1021                         return defaultValue;
1022                 }
1023                 if (val instanceof Boolean) {
1024                         return ((Boolean) val).booleanValue();
1025                 }
1026                 try {
1027                         // we'll use the get anyway because it does string conversion.
1028                         return this.getBoolean(key);
1029                 } catch (Exception e) {
1030                         return defaultValue;
1031                 }
1032         }
1033
1034         /**
1035          * Get an optional BigDecimal associated with a key, or the defaultValue if
1036          * there is no such key or if its value is not a number. If the value is a
1037          * string, an attempt will be made to evaluate it as a number.
1038          *
1039          * @param key          A key string.
1040          * @param defaultValue The default.
1041          * @return An object which is the value.
1042          */
1043         public BigDecimal optBigDecimal(String key, BigDecimal defaultValue) {
1044                 Object val = this.opt(key);
1045                 if (NULL.equals(val)) {
1046                         return defaultValue;
1047                 }
1048                 if (val instanceof BigDecimal) {
1049                         return (BigDecimal) val;
1050                 }
1051                 if (val instanceof BigInteger) {
1052                         return new BigDecimal((BigInteger) val);
1053                 }
1054                 if (val instanceof Double || val instanceof Float) {
1055                         return new BigDecimal(((Number) val).doubleValue());
1056                 }
1057                 if (val instanceof Long || val instanceof Integer || val instanceof Short || val instanceof Byte) {
1058                         return new BigDecimal(((Number) val).longValue());
1059                 }
1060                 // don't check if it's a string in case of unchecked Number subclasses
1061                 try {
1062                         return new BigDecimal(val.toString());
1063                 } catch (Exception e) {
1064                         return defaultValue;
1065                 }
1066         }
1067
1068         /**
1069          * Get an optional BigInteger associated with a key, or the defaultValue if
1070          * there is no such key or if its value is not a number. If the value is a
1071          * string, an attempt will be made to evaluate it as a number.
1072          *
1073          * @param key          A key string.
1074          * @param defaultValue The default.
1075          * @return An object which is the value.
1076          */
1077         public BigInteger optBigInteger(String key, BigInteger defaultValue) {
1078                 Object val = this.opt(key);
1079                 if (NULL.equals(val)) {
1080                         return defaultValue;
1081                 }
1082                 if (val instanceof BigInteger) {
1083                         return (BigInteger) val;
1084                 }
1085                 if (val instanceof BigDecimal) {
1086                         return ((BigDecimal) val).toBigInteger();
1087                 }
1088                 if (val instanceof Double || val instanceof Float) {
1089                         return new BigDecimal(((Number) val).doubleValue()).toBigInteger();
1090                 }
1091                 if (val instanceof Long || val instanceof Integer || val instanceof Short || val instanceof Byte) {
1092                         return BigInteger.valueOf(((Number) val).longValue());
1093                 }
1094                 // don't check if it's a string in case of unchecked Number subclasses
1095                 try {
1096                         // the other opt functions handle implicit conversions, i.e.
1097                         // jo.put("double",1.1d);
1098                         // jo.optInt("double"); -- will return 1, not an error
1099                         // this conversion to BigDecimal then to BigInteger is to maintain
1100                         // that type cast support that may truncate the decimal.
1101                         final String valStr = val.toString();
1102                         if (isDecimalNotation(valStr)) {
1103                                 return new BigDecimal(valStr).toBigInteger();
1104                         }
1105                         return new BigInteger(valStr);
1106                 } catch (Exception e) {
1107                         return defaultValue;
1108                 }
1109         }
1110
1111         /**
1112          * Get an optional double associated with a key, or NaN if there is no such key
1113          * or if its value is not a number. If the value is a string, an attempt will be
1114          * made to evaluate it as a number.
1115          *
1116          * @param key A string which is the key.
1117          * @return An object which is the value.
1118          */
1119         public double optDouble(String key) {
1120                 return this.optDouble(key, Double.NaN);
1121         }
1122
1123         /**
1124          * Get an optional double associated with a key, or the defaultValue if there is
1125          * no such key or if its value is not a number. If the value is a string, an
1126          * attempt will be made to evaluate it as a number.
1127          *
1128          * @param key          A key string.
1129          * @param defaultValue The default.
1130          * @return An object which is the value.
1131          */
1132         public double optDouble(String key, double defaultValue) {
1133                 Object val = this.opt(key);
1134                 if (NULL.equals(val)) {
1135                         return defaultValue;
1136                 }
1137                 if (val instanceof Number) {
1138                         return ((Number) val).doubleValue();
1139                 }
1140                 if (val instanceof String) {
1141                         try {
1142                                 return Double.parseDouble((String) val);
1143                         } catch (Exception e) {
1144                                 return defaultValue;
1145                         }
1146                 }
1147                 return defaultValue;
1148         }
1149
1150         /**
1151          * Get the optional double value associated with an index. NaN is returned if
1152          * there is no value for the index, or if the value is not a number and cannot
1153          * be converted to a number.
1154          *
1155          * @param key A key string.
1156          * @return The value.
1157          */
1158         public float optFloat(String key) {
1159                 return this.optFloat(key, Float.NaN);
1160         }
1161
1162         /**
1163          * Get the optional double value associated with an index. The defaultValue is
1164          * returned if there is no value for the index, or if the value is not a number
1165          * and cannot be converted to a number.
1166          *
1167          * @param key          A key string.
1168          * @param defaultValue The default value.
1169          * @return The value.
1170          */
1171         public float optFloat(String key, float defaultValue) {
1172                 Object val = this.opt(key);
1173                 if (JSONObject.NULL.equals(val)) {
1174                         return defaultValue;
1175                 }
1176                 if (val instanceof Number) {
1177                         return ((Number) val).floatValue();
1178                 }
1179                 if (val instanceof String) {
1180                         try {
1181                                 return Float.parseFloat((String) val);
1182                         } catch (Exception e) {
1183                                 return defaultValue;
1184                         }
1185                 }
1186                 return defaultValue;
1187         }
1188
1189         /**
1190          * Get an optional int value associated with a key, or zero if there is no such
1191          * key or if the value is not a number. If the value is a string, an attempt
1192          * will be made to evaluate it as a number.
1193          *
1194          * @param key A key string.
1195          * @return An object which is the value.
1196          */
1197         public int optInt(String key) {
1198                 return this.optInt(key, 0);
1199         }
1200
1201         /**
1202          * Get an optional int value associated with a key, or the default if there is
1203          * no such key or if the value is not a number. If the value is a string, an
1204          * attempt will be made to evaluate it as a number.
1205          *
1206          * @param key          A key string.
1207          * @param defaultValue The default.
1208          * @return An object which is the value.
1209          */
1210         public int optInt(String key, int defaultValue) {
1211                 Object val = this.opt(key);
1212                 if (NULL.equals(val)) {
1213                         return defaultValue;
1214                 }
1215                 if (val instanceof Number) {
1216                         return ((Number) val).intValue();
1217                 }
1218
1219                 if (val instanceof String) {
1220                         try {
1221                                 return new BigDecimal((String) val).intValue();
1222                         } catch (Exception e) {
1223                                 return defaultValue;
1224                         }
1225                 }
1226                 return defaultValue;
1227         }
1228
1229         /**
1230          * Get an optional JSONArray associated with a key. It returns null if there is
1231          * no such key, or if its value is not a JSONArray.
1232          *
1233          * @param key A key string.
1234          * @return A JSONArray which is the value.
1235          */
1236         public JSONArray optJSONArray(String key) {
1237                 Object o = this.opt(key);
1238                 return o instanceof JSONArray ? (JSONArray) o : null;
1239         }
1240
1241         /**
1242          * Get an optional JSONObject associated with a key. It returns null if there is
1243          * no such key, or if its value is not a JSONObject.
1244          *
1245          * @param key A key string.
1246          * @return A JSONObject which is the value.
1247          */
1248         public JSONObject optJSONObject(String key) {
1249                 Object object = this.opt(key);
1250                 return object instanceof JSONObject ? (JSONObject) object : null;
1251         }
1252
1253         /**
1254          * Get an optional long value associated with a key, or zero if there is no such
1255          * key or if the value is not a number. If the value is a string, an attempt
1256          * will be made to evaluate it as a number.
1257          *
1258          * @param key A key string.
1259          * @return An object which is the value.
1260          */
1261         public long optLong(String key) {
1262                 return this.optLong(key, 0);
1263         }
1264
1265         /**
1266          * Get an optional long value associated with a key, or the default if there is
1267          * no such key or if the value is not a number. If the value is a string, an
1268          * attempt will be made to evaluate it as a number.
1269          *
1270          * @param key          A key string.
1271          * @param defaultValue The default.
1272          * @return An object which is the value.
1273          */
1274         public long optLong(String key, long defaultValue) {
1275                 Object val = this.opt(key);
1276                 if (NULL.equals(val)) {
1277                         return defaultValue;
1278                 }
1279                 if (val instanceof Number) {
1280                         return ((Number) val).longValue();
1281                 }
1282
1283                 if (val instanceof String) {
1284                         try {
1285                                 return new BigDecimal((String) val).longValue();
1286                         } catch (Exception e) {
1287                                 return defaultValue;
1288                         }
1289                 }
1290                 return defaultValue;
1291         }
1292
1293         /**
1294          * Get an optional {@link Number} value associated with a key, or
1295          * <code>null</code> if there is no such key or if the value is not a number. If
1296          * the value is a string, an attempt will be made to evaluate it as a number
1297          * ({@link BigDecimal}). This method would be used in cases where type coercion
1298          * of the number value is unwanted.
1299          *
1300          * @param key A key string.
1301          * @return An object which is the value.
1302          */
1303         public Number optNumber(String key) {
1304                 return this.optNumber(key, null);
1305         }
1306
1307         /**
1308          * Get an optional {@link Number} value associated with a key, or the default if
1309          * there is no such key or if the value is not a number. If the value is a
1310          * string, an attempt will be made to evaluate it as a number. This method would
1311          * be used in cases where type coercion of the number value is unwanted.
1312          *
1313          * @param key          A key string.
1314          * @param defaultValue The default.
1315          * @return An object which is the value.
1316          */
1317         public Number optNumber(String key, Number defaultValue) {
1318                 Object val = this.opt(key);
1319                 if (NULL.equals(val)) {
1320                         return defaultValue;
1321                 }
1322                 if (val instanceof Number) {
1323                         return (Number) val;
1324                 }
1325
1326                 if (val instanceof String) {
1327                         try {
1328                                 return stringToNumber((String) val);
1329                         } catch (Exception e) {
1330                                 return defaultValue;
1331                         }
1332                 }
1333                 return defaultValue;
1334         }
1335
1336         /**
1337          * Get an optional string associated with a key. It returns an empty string if
1338          * there is no such key. If the value is not a string and is not null, then it
1339          * is converted to a string.
1340          *
1341          * @param key A key string.
1342          * @return A string which is the value.
1343          */
1344         public String optString(String key) {
1345                 return this.optString(key, "");
1346         }
1347
1348         /**
1349          * Get an optional string associated with a key. It returns the defaultValue if
1350          * there is no such key.
1351          *
1352          * @param key          A key string.
1353          * @param defaultValue The default.
1354          * @return A string which is the value.
1355          */
1356         public String optString(String key, String defaultValue) {
1357                 Object object = this.opt(key);
1358                 return NULL.equals(object) ? defaultValue : object.toString();
1359         }
1360
1361         /**
1362          * Populates the internal map of the JSONObject with the bean properties. The
1363          * bean can not be recursive.
1364          *
1365          * @see JSONObject#JSONObject(Object)
1366          *
1367          * @param bean the bean
1368          */
1369         private void populateMap(Object bean) {
1370                 Class<?> klass = bean.getClass();
1371
1372                 // If klass is a System class then set includeSuperClass to false.
1373
1374                 boolean includeSuperClass = klass.getClassLoader() != null;
1375
1376                 Method[] methods = includeSuperClass ? klass.getMethods() : klass.getDeclaredMethods();
1377                 for (final Method method : methods) {
1378                         final int modifiers = method.getModifiers();
1379                         if (Modifier.isPublic(modifiers) && !Modifier.isStatic(modifiers) && method.getParameterTypes().length == 0
1380                                         && !method.isBridge() && method.getReturnType() != Void.TYPE
1381                                         && isValidMethodName(method.getName())) {
1382                                 final String key = getKeyNameFromMethod(method);
1383                                 if (key != null && !key.isEmpty()) {
1384                                         try {
1385                                                 final Object result = method.invoke(bean);
1386                                                 if (result != null) {
1387                                                         this.map.put(key, wrap(result));
1388                                                         // we don't use the result anywhere outside of wrap
1389                                                         // if it's a resource we should be sure to close it
1390                                                         // after calling toString
1391                                                         if (result instanceof Closeable) {
1392                                                                 try {
1393                                                                         ((Closeable) result).close();
1394                                                                 } catch (IOException ignore) {
1395                                                                 }
1396                                                         }
1397                                                 }
1398                                         } catch (IllegalAccessException ignore) {
1399                                         } catch (IllegalArgumentException ignore) {
1400                                         } catch (InvocationTargetException ignore) {
1401                                         }
1402                                 }
1403                         }
1404                 }
1405         }
1406
1407         private boolean isValidMethodName(String name) {
1408                 return !"getClass".equals(name) && !"getDeclaringClass".equals(name);
1409         }
1410
1411         private String getKeyNameFromMethod(Method method) {
1412                 final int ignoreDepth = -1;// getAnnotationDepth(method, JSONPropertyIgnore.class);
1413 //        if (ignoreDepth > 0) {
1414 //            final int forcedNameDepth = getAnnotationDepth(method, JSONPropertyName.class);
1415 //            if (forcedNameDepth < 0 || ignoreDepth <= forcedNameDepth) {
1416 //                // the hierarchy asked to ignore, and the nearest name override
1417 //                // was higher or non-existent
1418 //                return null;
1419 //            }
1420 //        }
1421 //        JSONPropertyName annotation = getAnnotation(method, JSONPropertyName.class);
1422 //        if (annotation != null && annotation.value() != null && !annotation.value().isEmpty()) {
1423 //            return annotation.value();
1424 //        }
1425                 String key;
1426                 final String name = method.getName();
1427                 if (name.startsWith("get") && name.length() > 3) {
1428                         key = name.substring(3);
1429                 } else if (name.startsWith("is") && name.length() > 2) {
1430                         key = name.substring(2);
1431                 } else {
1432                         return null;
1433                 }
1434                 // if the first letter in the key is not uppercase, then skip.
1435                 // This is to maintain backwards compatibility before PR406
1436                 // (https://github.com/stleary/JSON-java/pull/406/)
1437                 if (Character.isLowerCase(key.charAt(0))) {
1438                         return null;
1439                 }
1440                 if (key.length() == 1) {
1441                         key = key.toLowerCase(Locale.ROOT);
1442                 } else if (!Character.isUpperCase(key.charAt(1))) {
1443                         key = key.substring(0, 1).toLowerCase(Locale.ROOT) + key.substring(1);
1444                 }
1445                 return (/** @j2sNative 1 ? key.split("$")[0] : */
1446                 key);
1447         }
1448
1449 //    /**
1450 //     * Searches the class hierarchy to see if the method or it's super
1451 //     * implementations and interfaces has the annotation.
1452 //     *
1453 //     * @param <A>
1454 //     *            type of the annotation
1455 //     *
1456 //     * @param m
1457 //     *            method to check
1458 //     * @param annotationClass
1459 //     *            annotation to look for
1460 //     * @return the {@link Annotation} if the annotation exists on the current method
1461 //     *         or one of it's super class definitions
1462 //     */
1463 //    private static <A extends Annotation> A getAnnotation(final Method m, final Class<A> annotationClass) {
1464 //      return null;
1465 //        // if we have invalid data the result is null
1466 //        if (true || m == null || annotationClass == null) {
1467 //            return null;
1468 //        }
1469 //
1470 //        if (m.isAnnotationPresent(annotationClass)) {
1471 //            return m.getAnnotation(annotationClass);
1472 //        }
1473 //
1474 //        // if we've already reached the Object class, return null;
1475 //        Class<?> c = m.getDeclaringClass();
1476 //        if (c.getSuperclass() == null) {
1477 //            return null;
1478 //        }
1479 //
1480 //        // check directly implemented interfaces for the method being checked
1481 //        for (Class<?> i : c.getInterfaces()) {
1482 //            try {
1483 //                Method im = i.getMethod(m.getName(), m.getParameterTypes());
1484 //                return getAnnotation(im, annotationClass);
1485 //            } catch (final SecurityException ex) {
1486 //                continue;
1487 //            } catch (final NoSuchMethodException ex) {
1488 //                continue;
1489 //            }
1490 //        }
1491 //
1492 //        try {
1493 //            return getAnnotation(
1494 //                    c.getSuperclass().getMethod(m.getName(), m.getParameterTypes()),
1495 //                    annotationClass);
1496 //        } catch (final SecurityException ex) {
1497 //            return null;
1498 //        } catch (final NoSuchMethodException ex) {
1499 //            return null;
1500 //        }
1501 //    }
1502 //
1503 //    /**
1504 //     * Searches the class hierarchy to see if the method or it's super
1505 //     * implementations and interfaces has the annotation. Returns the depth of the
1506 //     * annotation in the hierarchy.
1507 //     *
1508 //     * @param <A>
1509 //     *            type of the annotation
1510 //     *
1511 //     * @param m
1512 //     *            method to check
1513 //     * @param annotationClass
1514 //     *            annotation to look for
1515 //     * @return Depth of the annotation or -1 if the annotation is not on the method.
1516 //     */
1517 //    private static int getAnnotationDepth(final Method m, final Class<? extends Annotation> annotationClass) {
1518 //        // if we have invalid data the result is -1
1519 //        if (m == null || annotationClass == null) {
1520 //            return -1;
1521 //        }
1522 //        if (m.isAnnotationPresent(annotationClass)) {
1523 //            return 1;
1524 //        }
1525 //
1526 //        // if we've already reached the Object class, return -1;
1527 //        Class<?> c = m.getDeclaringClass();
1528 //        if (c.getSuperclass() == null) {
1529 //            return -1;
1530 //        }
1531 //
1532 //        // check directly implemented interfaces for the method being checked
1533 //        for (Class<?> i : c.getInterfaces()) {
1534 //            try {
1535 //                Method im = i.getMethod(m.getName(), m.getParameterTypes());
1536 //                int d = getAnnotationDepth(im, annotationClass);
1537 //                if (d > 0) {
1538 //                    // since the annotation was on the interface, add 1
1539 //                    return d + 1;
1540 //                }
1541 //            } catch (final SecurityException ex) {
1542 //                continue;
1543 //            } catch (final NoSuchMethodException ex) {
1544 //                continue;
1545 //            }
1546 //        }
1547 //
1548 //        try {
1549 //            int d = getAnnotationDepth(
1550 //                    c.getSuperclass().getMethod(m.getName(), m.getParameterTypes()),
1551 //                    annotationClass);
1552 //            if (d > 0) {
1553 //                // since the annotation was on the superclass, add 1
1554 //                return d + 1;
1555 //            }
1556 //            return -1;
1557 //        } catch (final SecurityException ex) {
1558 //            return -1;
1559 //        } catch (final NoSuchMethodException ex) {
1560 //            return -1;
1561 //        }
1562 //    }
1563
1564         /**
1565          * Put a key/boolean pair in the JSONObject.
1566          *
1567          * @param key   A key string.
1568          * @param value A boolean which is the value.
1569          * @return this.
1570          * @throws JSONException        If the value is non-finite number.
1571          * @throws NullPointerException If the key is <code>null</code>.
1572          */
1573         public JSONObject put(String key, boolean value) throws JSONException {
1574                 return this.put(key, value ? Boolean.TRUE : Boolean.FALSE);
1575         }
1576
1577         /**
1578          * Put a key/value pair in the JSONObject, where the value will be a JSONArray
1579          * which is produced from a Collection.
1580          *
1581          * @param key   A key string.
1582          * @param value A Collection value.
1583          * @return this.
1584          * @throws JSONException        If the value is non-finite number.
1585          * @throws NullPointerException If the key is <code>null</code>.
1586          */
1587         public JSONObject put(String key, Collection<?> value) throws JSONException {
1588                 return this.put(key, new JSONArray(value));
1589         }
1590
1591         /**
1592          * Put a key/double pair in the JSONObject.
1593          *
1594          * @param key   A key string.
1595          * @param value A double which is the value.
1596          * @return this.
1597          * @throws JSONException        If the value is non-finite number.
1598          * @throws NullPointerException If the key is <code>null</code>.
1599          */
1600         public JSONObject put(String key, double value) throws JSONException {
1601                 return this.put(key, Double.valueOf(value));
1602         }
1603
1604         /**
1605          * Put a key/float pair in the JSONObject.
1606          *
1607          * @param key   A key string.
1608          * @param value A float which is the value.
1609          * @return this.
1610          * @throws JSONException        If the value is non-finite number.
1611          * @throws NullPointerException If the key is <code>null</code>.
1612          */
1613         public JSONObject put(String key, float value) throws JSONException {
1614                 return this.put(key, Float.valueOf(value));
1615         }
1616
1617         /**
1618          * Put a key/int pair in the JSONObject.
1619          *
1620          * @param key   A key string.
1621          * @param value An int which is the value.
1622          * @return this.
1623          * @throws JSONException        If the value is non-finite number.
1624          * @throws NullPointerException If the key is <code>null</code>.
1625          */
1626         public JSONObject put(String key, int value) throws JSONException {
1627                 return this.put(key, Integer.valueOf(value));
1628         }
1629
1630         /**
1631          * Put a key/long pair in the JSONObject.
1632          *
1633          * @param key   A key string.
1634          * @param value A long which is the value.
1635          * @return this.
1636          * @throws JSONException        If the value is non-finite number.
1637          * @throws NullPointerException If the key is <code>null</code>.
1638          */
1639         public JSONObject put(String key, long value) throws JSONException {
1640                 return this.put(key, Long.valueOf(value));
1641         }
1642
1643         /**
1644          * Put a key/value pair in the JSONObject, where the value will be a JSONObject
1645          * which is produced from a Map.
1646          *
1647          * @param key   A key string.
1648          * @param value A Map value.
1649          * @return this.
1650          * @throws JSONException        If the value is non-finite number.
1651          * @throws NullPointerException If the key is <code>null</code>.
1652          */
1653         public JSONObject put(String key, Map<?, ?> value) throws JSONException {
1654                 return this.put(key, new JSONObject(value));
1655         }
1656
1657         /**
1658          * Put a key/value pair in the JSONObject. If the value is <code>null</code>,
1659          * then the key will be removed from the JSONObject if it is present.
1660          *
1661          * @param key   A key string.
1662          * @param value An object which is the value. It should be of one of these
1663          *              types: Boolean, Double, Integer, JSONArray, JSONObject, Long,
1664          *              String, or the JSONObject.NULL object.
1665          * @return this.
1666          * @throws JSONException        If the value is non-finite number.
1667          * @throws NullPointerException If the key is <code>null</code>.
1668          */
1669         public JSONObject put(String key, Object value) throws JSONException {
1670                 if (key == null) {
1671                         throw new NullPointerException("Null key.");
1672                 }
1673                 if (value != null) {
1674                         testValidity(value);
1675                         this.map.put(key, value);
1676                 } else {
1677                         this.remove(key);
1678                 }
1679                 return this;
1680         }
1681
1682         /**
1683          * Put a key/value pair in the JSONObject, but only if the key and the value are
1684          * both non-null, and only if there is not already a member with that name.
1685          *
1686          * @param key   string
1687          * @param value object
1688          * @return this.
1689          * @throws JSONException if the key is a duplicate
1690          */
1691         public JSONObject putOnce(String key, Object value) throws JSONException {
1692                 if (key != null && value != null) {
1693                         if (this.opt(key) != null) {
1694                                 throw new JSONException("Duplicate key \"" + key + "\"");
1695                         }
1696                         return this.put(key, value);
1697                 }
1698                 return this;
1699         }
1700
1701         /**
1702          * Put a key/value pair in the JSONObject, but only if the key and the value are
1703          * both non-null.
1704          *
1705          * @param key   A key string.
1706          * @param value An object which is the value. It should be of one of these
1707          *              types: Boolean, Double, Integer, JSONArray, JSONObject, Long,
1708          *              String, or the JSONObject.NULL object.
1709          * @return this.
1710          * @throws JSONException If the value is a non-finite number.
1711          */
1712         public JSONObject putOpt(String key, Object value) throws JSONException {
1713                 if (key != null && value != null) {
1714                         return this.put(key, value);
1715                 }
1716                 return this;
1717         }
1718
1719         /**
1720          * Creates a JSONPointer using an initialization string and tries to match it to
1721          * an item within this JSONObject. For example, given a JSONObject initialized
1722          * with this document:
1723          * 
1724          * <pre>
1725          * {
1726          *     "a":{"b":"c"}
1727          * }
1728          * </pre>
1729          * 
1730          * and this JSONPointer string:
1731          * 
1732          * <pre>
1733          * "/a/b"
1734          * </pre>
1735          * 
1736          * Then this method will return the String "c". A JSONPointerException may be
1737          * thrown from code called by this method.
1738          * 
1739          * @param jsonPointer string that can be used to create a JSONPointer
1740          * @return the item matched by the JSONPointer, otherwise null
1741          */
1742         public Object query(String jsonPointer) {
1743                 return query(new JSONPointer(jsonPointer));
1744         }
1745
1746         /**
1747          * Uses a user initialized JSONPointer and tries to match it to an item within
1748          * this JSONObject. For example, given a JSONObject initialized with this
1749          * document:
1750          * 
1751          * <pre>
1752          * {
1753          *     "a":{"b":"c"}
1754          * }
1755          * </pre>
1756          * 
1757          * and this JSONPointer:
1758          * 
1759          * <pre>
1760          * "/a/b"
1761          * </pre>
1762          * 
1763          * Then this method will return the String "c". A JSONPointerException may be
1764          * thrown from code called by this method.
1765          * 
1766          * @param jsonPointer string that can be used to create a JSONPointer
1767          * @return the item matched by the JSONPointer, otherwise null
1768          */
1769         public Object query(JSONPointer jsonPointer) {
1770                 return jsonPointer.queryFrom(this);
1771         }
1772
1773         /**
1774          * Queries and returns a value from this object using {@code jsonPointer}, or
1775          * returns null if the query fails due to a missing key.
1776          * 
1777          * @param jsonPointer the string representation of the JSON pointer
1778          * @return the queried value or {@code null}
1779          * @throws IllegalArgumentException if {@code jsonPointer} has invalid syntax
1780          */
1781         public Object optQuery(String jsonPointer) {
1782                 return optQuery(new JSONPointer(jsonPointer));
1783         }
1784
1785         /**
1786          * Queries and returns a value from this object using {@code jsonPointer}, or
1787          * returns null if the query fails due to a missing key.
1788          * 
1789          * @param jsonPointer The JSON pointer
1790          * @return the queried value or {@code null}
1791          * @throws IllegalArgumentException if {@code jsonPointer} has invalid syntax
1792          */
1793         public Object optQuery(JSONPointer jsonPointer) {
1794                 try {
1795                         return jsonPointer.queryFrom(this);
1796                 } catch (JSONPointerException e) {
1797                         return null;
1798                 }
1799         }
1800
1801         /**
1802          * Produce a string in double quotes with backslash sequences in all the right
1803          * places. A backslash will be inserted within </, producing <\/, allowing JSON
1804          * text to be delivered in HTML. In JSON text, a string cannot contain a control
1805          * character or an unescaped quote or backslash.
1806          *
1807          * @param string A String
1808          * @return A String correctly formatted for insertion in a JSON text.
1809          */
1810         public static String quote(String string) {
1811                 StringWriter sw = new StringWriter();
1812                 synchronized (sw.getBuffer()) {
1813                         try {
1814                                 return quote(string, sw).toString();
1815                         } catch (IOException ignored) {
1816                                 // will never happen - we are writing to a string writer
1817                                 return "";
1818                         }
1819                 }
1820         }
1821
1822         public static Writer quote(String string, Writer w) throws IOException {
1823                 if (string == null || string.isEmpty()) {
1824                         w.write("\"\"");
1825                         return w;
1826                 }
1827
1828                 char b;
1829                 char c = 0;
1830                 String hhhh;
1831                 int i;
1832                 int len = string.length();
1833
1834                 w.write('"');
1835                 for (i = 0; i < len; i += 1) {
1836                         b = c;
1837                         c = string.charAt(i);
1838                         switch (c) {
1839                         case '\\':
1840                         case '"':
1841                                 w.write('\\');
1842                                 w.write(c);
1843                                 break;
1844                         case '/':
1845                                 if (b == '<') {
1846                                         w.write('\\');
1847                                 }
1848                                 w.write(c);
1849                                 break;
1850                         case '\b':
1851                                 w.write("\\b");
1852                                 break;
1853                         case '\t':
1854                                 w.write("\\t");
1855                                 break;
1856                         case '\n':
1857                                 w.write("\\n");
1858                                 break;
1859                         case '\f':
1860                                 w.write("\\f");
1861                                 break;
1862                         case '\r':
1863                                 w.write("\\r");
1864                                 break;
1865                         default:
1866                                 if (c < ' ' || (c >= '\u0080' && c < '\u00a0') || (c >= '\u2000' && c < '\u2100')) {
1867                                         w.write("\\u");
1868                                         hhhh = Integer.toHexString(c);
1869                                         w.write("0000", 0, 4 - hhhh.length());
1870                                         w.write(hhhh);
1871                                 } else {
1872                                         w.write(c);
1873                                 }
1874                         }
1875                 }
1876                 w.write('"');
1877                 return w;
1878         }
1879
1880         /**
1881          * Remove a name and its value, if present.
1882          *
1883          * @param key The name to be removed.
1884          * @return The value that was associated with the name, or null if there was no
1885          *         value.
1886          */
1887         public Object remove(String key) {
1888                 return this.map.remove(key);
1889         }
1890
1891         /**
1892          * Determine if two JSONObjects are similar. They must contain the same set of
1893          * names which must be associated with similar values.
1894          *
1895          * @param other The other JSONObject
1896          * @return true if they are equal
1897          */
1898         public boolean similar(Object other) {
1899                 try {
1900                         if (!(other instanceof JSONObject)) {
1901                                 return false;
1902                         }
1903                         if (!this.keySet().equals(((JSONObject) other).keySet())) {
1904                                 return false;
1905                         }
1906                         for (final Entry<String, ?> entry : this.entrySet()) {
1907                                 String name = entry.getKey();
1908                                 Object valueThis = entry.getValue();
1909                                 Object valueOther = ((JSONObject) other).get(name);
1910                                 if (valueThis == valueOther) {
1911                                         continue;
1912                                 }
1913                                 if (valueThis == null) {
1914                                         return false;
1915                                 }
1916                                 if (valueThis instanceof JSONObject) {
1917                                         if (!((JSONObject) valueThis).similar(valueOther)) {
1918                                                 return false;
1919                                         }
1920                                 } else if (valueThis instanceof JSONArray) {
1921                                         if (!((JSONArray) valueThis).similar(valueOther)) {
1922                                                 return false;
1923                                         }
1924                                 } else if (!valueThis.equals(valueOther)) {
1925                                         return false;
1926                                 }
1927                         }
1928                         return true;
1929                 } catch (Throwable exception) {
1930                         return false;
1931                 }
1932         }
1933
1934         /**
1935          * Tests if the value should be tried as a decimal. It makes no test if there
1936          * are actual digits.
1937          * 
1938          * @param val value to test
1939          * @return true if the string is "-0" or if it contains '.', 'e', or 'E', false
1940          *         otherwise.
1941          */
1942         protected static boolean isDecimalNotation(final String val) {
1943                 return val.indexOf('.') > -1 || val.indexOf('e') > -1 || val.indexOf('E') > -1 || "-0".equals(val);
1944         }
1945
1946         /**
1947          * Converts a string to a number using the narrowest possible type. Possible
1948          * returns for this function are BigDecimal, Double, BigInteger, Long, and
1949          * Integer. When a Double is returned, it should always be a valid Double and
1950          * not NaN or +-infinity.
1951          * 
1952          * @param val value to convert
1953          * @return Number representation of the value.
1954          * @throws NumberFormatException thrown if the value is not a valid number. A
1955          *                               public caller should catch this and wrap it in
1956          *                               a {@link JSONException} if applicable.
1957          */
1958         protected static Number stringToNumber(final String val) throws NumberFormatException {
1959                 char initial = val.charAt(0);
1960                 if ((initial >= '0' && initial <= '9') || initial == '-') {
1961                         // decimal representation
1962                         if (isDecimalNotation(val)) {
1963                                 // quick dirty way to see if we need a BigDecimal instead of a Double
1964                                 // this only handles some cases of overflow or underflow
1965                                 if (val.length() > 14) {
1966                                         return new BigDecimal(val);
1967                                 }
1968                                 final Double d = Double.valueOf(val);
1969                                 if (d.isInfinite() || d.isNaN()) {
1970                                         // if we can't parse it as a double, go up to BigDecimal
1971                                         // this is probably due to underflow like 4.32e-678
1972                                         // or overflow like 4.65e5324. The size of the string is small
1973                                         // but can't be held in a Double.
1974                                         return new BigDecimal(val);
1975                                 }
1976                                 return d;
1977                         }
1978                         // integer representation.
1979                         // This will narrow any values to the smallest reasonable Object representation
1980                         // (Integer, Long, or BigInteger)
1981
1982                         // string version
1983                         // The compare string length method reduces GC,
1984                         // but leads to smaller integers being placed in larger wrappers even though not
1985                         // needed. i.e. 1,000,000,000 -> Long even though it's an Integer
1986                         // 1,000,000,000,000,000,000 -> BigInteger even though it's a Long
1987                         // if(val.length()<=9){
1988                         // return Integer.valueOf(val);
1989                         // }
1990                         // if(val.length()<=18){
1991                         // return Long.valueOf(val);
1992                         // }
1993                         // return new BigInteger(val);
1994
1995                         // BigInteger version: We use a similar bitLenth compare as
1996                         // BigInteger#intValueExact uses. Increases GC, but objects hold
1997                         // only what they need. i.e. Less runtime overhead if the value is
1998                         // long lived. Which is the better tradeoff? This is closer to what's
1999                         // in stringToValue.
2000                         BigInteger bi = new BigInteger(val);
2001                         if (bi.bitLength() <= 31) {
2002                                 return Integer.valueOf(bi.intValue());
2003                         }
2004                         if (bi.bitLength() <= 63) {
2005                                 return Long.valueOf(bi.longValue());
2006                         }
2007                         return bi;
2008                 }
2009                 throw new NumberFormatException("val [" + val + "] is not a valid number.");
2010         }
2011
2012         /**
2013          * Try to convert a string into a number, boolean, or null. If the string can't
2014          * be converted, return the string.
2015          *
2016          * @param string A String.
2017          * @return A simple JSON value.
2018          */
2019         // Changes to this method must be copied to the corresponding method in
2020         // the XML class to keep full support for Android
2021         public static Object stringToValue(String string) {
2022                 if (string.equals("")) {
2023                         return string;
2024                 }
2025                 if (string.equalsIgnoreCase("true")) {
2026                         return Boolean.TRUE;
2027                 }
2028                 if (string.equalsIgnoreCase("false")) {
2029                         return Boolean.FALSE;
2030                 }
2031                 if (string.equalsIgnoreCase("null")) {
2032                         return JSONObject.NULL;
2033                 }
2034
2035                 /*
2036                  * If it might be a number, try converting it. If a number cannot be produced,
2037                  * then the value will just be a string.
2038                  */
2039
2040                 char initial = string.charAt(0);
2041                 if ((initial >= '0' && initial <= '9') || initial == '-') {
2042                         try {
2043                                 // if we want full Big Number support this block can be replaced with:
2044                                 // return stringToNumber(string);
2045                                 if (isDecimalNotation(string)) {
2046                                         Double d = Double.valueOf(string);
2047                                         if (!d.isInfinite() && !d.isNaN()) {
2048                                                 return d;
2049                                         }
2050                                 } else {
2051                                         Long myLong = Long.valueOf(string);
2052                                         if (string.equals(myLong.toString())) {
2053                                                 if (myLong.longValue() == myLong.intValue()) {
2054                                                         return Integer.valueOf(myLong.intValue());
2055                                                 }
2056                                                 return myLong;
2057                                         }
2058                                 }
2059                         } catch (Exception ignore) {
2060                         }
2061                 }
2062                 return string;
2063         }
2064
2065         /**
2066          * Throw an exception if the object is a NaN or infinite number.
2067          *
2068          * @param o The object to test.
2069          * @throws JSONException If o is a non-finite number.
2070          */
2071         public static void testValidity(Object o) throws JSONException {
2072                 if (o != null) {
2073                         if (o instanceof Double) {
2074                                 if (((Double) o).isInfinite() || ((Double) o).isNaN()) {
2075                                         throw new JSONException("JSON does not allow non-finite numbers.");
2076                                 }
2077                         } else if (o instanceof Float) {
2078                                 if (((Float) o).isInfinite() || ((Float) o).isNaN()) {
2079                                         throw new JSONException("JSON does not allow non-finite numbers.");
2080                                 }
2081                         }
2082                 }
2083         }
2084
2085         /**
2086          * Produce a JSONArray containing the values of the members of this JSONObject.
2087          *
2088          * @param names A JSONArray containing a list of key strings. This determines
2089          *              the sequence of the values in the result.
2090          * @return A JSONArray of values.
2091          * @throws JSONException If any of the values are non-finite numbers.
2092          */
2093         public JSONArray toJSONArray(JSONArray names) throws JSONException {
2094                 if (names == null || names.isEmpty()) {
2095                         return null;
2096                 }
2097                 JSONArray ja = new JSONArray();
2098                 for (int i = 0; i < names.length(); i += 1) {
2099                         ja.put(this.opt(names.getString(i)));
2100                 }
2101                 return ja;
2102         }
2103
2104         /**
2105          * Make a JSON text of this JSONObject. For compactness, no whitespace is added.
2106          * If this would not result in a syntactically correct JSON text, then null will
2107          * be returned instead.
2108          * <p>
2109          * <b> Warning: This method assumes that the data structure is acyclical. </b>
2110          * 
2111          * @return a printable, displayable, portable, transmittable representation of
2112          *         the object, beginning with <code>{</code>&nbsp;<small>(left
2113          *         brace)</small> and ending with <code>}</code>&nbsp;<small>(right
2114          *         brace)</small>.
2115          */
2116         @Override
2117         public String toString() {
2118                 try {
2119                         return this.toString(0);
2120                 } catch (Exception e) {
2121                         return null;
2122                 }
2123         }
2124
2125         /**
2126          * Make a pretty-printed JSON text of this JSONObject.
2127          * 
2128          * <p>
2129          * If <code>indentFactor > 0</code> and the {@link JSONObject} has only one key,
2130          * then the object will be output on a single line:
2131          * 
2132          * <pre>
2133          * {@code {"key": 1}}
2134          * </pre>
2135          * 
2136          * <p>
2137          * If an object has 2 or more keys, then it will be output across multiple
2138          * lines: <code><pre>{
2139          *  "key1": 1,
2140          *  "key2": "value 2",
2141          *  "key3": 3
2142          * }</pre></code>
2143          * <p>
2144          * <b> Warning: This method assumes that the data structure is acyclical. </b>
2145          *
2146          * @param indentFactor The number of spaces to add to each level of indentation.
2147          * @return a printable, displayable, portable, transmittable representation of
2148          *         the object, beginning with <code>{</code>&nbsp;<small>(left
2149          *         brace)</small> and ending with <code>}</code>&nbsp;<small>(right
2150          *         brace)</small>.
2151          * @throws JSONException If the object contains an invalid number.
2152          */
2153         public String toString(int indentFactor) throws JSONException {
2154                 StringWriter w = new StringWriter();
2155                 synchronized (w.getBuffer()) {
2156                         return this.write(w, indentFactor, 0).toString();
2157                 }
2158         }
2159
2160         /**
2161          * Make a JSON text of an Object value. If the object has an
2162          * value.toJSONString() method, then that method will be used to produce the
2163          * JSON text. The method is required to produce a strictly conforming text. If
2164          * the object does not contain a toJSONString method (which is the most common
2165          * case), then a text will be produced by other means. If the value is an array
2166          * or Collection, then a JSONArray will be made from it and its toJSONString
2167          * method will be called. If the value is a MAP, then a JSONObject will be made
2168          * from it and its toJSONString method will be called. Otherwise, the value's
2169          * toString method will be called, and the result will be quoted.
2170          *
2171          * <p>
2172          * Warning: This method assumes that the data structure is acyclical.
2173          *
2174          * @param value The value to be serialized.
2175          * @return a printable, displayable, transmittable representation of the object,
2176          *         beginning with <code>{</code>&nbsp;<small>(left brace)</small> and
2177          *         ending with <code>}</code>&nbsp;<small>(right brace)</small>.
2178          * @throws JSONException If the value is or contains an invalid number.
2179          */
2180         public static String valueToString(Object value) throws JSONException {
2181                 // moves the implementation to JSONWriter as:
2182                 // 1. It makes more sense to be part of the writer class
2183                 // 2. For Android support this method is not available. By implementing it in
2184                 // the Writer
2185                 // Android users can use the writer with the built in Android JSONObject
2186                 // implementation.
2187                 return JSONWriter.valueToString(value);
2188         }
2189
2190         /**
2191          * Wrap an object, if necessary. If the object is <code>null</code>, return the
2192          * NULL object. If it is an array or collection, wrap it in a JSONArray. If it
2193          * is a map, wrap it in a JSONObject. If it is a standard property (Double,
2194          * String, et al) then it is already wrapped. Otherwise, if it comes from one of
2195          * the java packages, turn it into a string. And if it doesn't, try to wrap it
2196          * in a JSONObject. If the wrapping fails, then null is returned.
2197          *
2198          * @param object The object to wrap
2199          * @return The wrapped value
2200          */
2201         public static Object wrap(Object object) {
2202                 try {
2203                         if (object == null) {
2204                                 return NULL;
2205                         }
2206                         if (object instanceof JSONObject || object instanceof JSONArray || NULL.equals(object)
2207                                         || object instanceof JSONString || object instanceof Byte || object instanceof Character
2208                                         || object instanceof Short || object instanceof Integer || object instanceof Long
2209                                         || object instanceof Boolean || object instanceof Float || object instanceof Double
2210                                         || object instanceof String || object instanceof BigInteger || object instanceof BigDecimal
2211                                         || object instanceof Enum) {
2212                                 return object;
2213                         }
2214
2215                         if (object instanceof Collection) {
2216                                 Collection<?> coll = (Collection<?>) object;
2217                                 return new JSONArray(coll);
2218                         }
2219                         if (object.getClass().isArray()) {
2220                                 return new JSONArray(object);
2221                         }
2222                         if (object instanceof Map) {
2223                                 Map<?, ?> map = (Map<?, ?>) object;
2224                                 return new JSONObject(map);
2225                         }
2226                         Package objectPackage = object.getClass().getPackage();
2227                         String objectPackageName = objectPackage != null ? objectPackage.getName() : "";
2228                         if (objectPackageName.startsWith("java.") || objectPackageName.startsWith("javax.")
2229                                         || object.getClass().getClassLoader() == null) {
2230                                 return object.toString();
2231                         }
2232                         return new JSONObject(object);
2233                 } catch (Exception exception) {
2234                         return null;
2235                 }
2236         }
2237
2238         /**
2239          * Write the contents of the JSONObject as JSON text to a writer. For
2240          * compactness, no whitespace is added.
2241          * <p>
2242          * <b> Warning: This method assumes that the data structure is acyclical. </b>
2243          * 
2244          * @return The writer.
2245          * @throws JSONException
2246          */
2247         public Writer write(Writer writer) throws JSONException {
2248                 return this.write(writer, 0, 0);
2249         }
2250
2251         static final Writer writeValue(Writer writer, Object value, int indentFactor, int indent)
2252                         throws JSONException, IOException {
2253                 if (value == null || value.equals(null)) {
2254                         writer.write("null");
2255                 } else if (value instanceof JSONString) {
2256                         Object o;
2257                         try {
2258                                 o = ((JSONString) value).toJSONString();
2259                         } catch (Exception e) {
2260                                 throw new JSONException(e);
2261                         }
2262                         writer.write(o != null ? o.toString() : quote(value.toString()));
2263                 } else if (value instanceof Number) {
2264                         // not all Numbers may match actual JSON Numbers. i.e. fractions or Imaginary
2265                         final String numberAsString = numberToString((Number) value);
2266                         try {
2267                                 // Use the BigDecimal constructor for its parser to validate the format.
2268                                 @SuppressWarnings("unused")
2269                                 BigDecimal testNum = new BigDecimal(numberAsString);
2270                                 // Close enough to a JSON number that we will use it unquoted
2271                                 writer.write(numberAsString);
2272                         } catch (NumberFormatException ex) {
2273                                 // The Number value is not a valid JSON number.
2274                                 // Instead we will quote it as a string
2275                                 quote(numberAsString, writer);
2276                         }
2277                 } else if (value instanceof Boolean) {
2278                         writer.write(value.toString());
2279                 } else if (value instanceof Enum<?>) {
2280                         writer.write(quote(((Enum<?>) value).name()));
2281                 } else if (value instanceof JSONObject) {
2282                         ((JSONObject) value).write(writer, indentFactor, indent);
2283                 } else if (value instanceof JSONArray) {
2284                         ((JSONArray) value).write(writer, indentFactor, indent);
2285                 } else if (value instanceof Map) {
2286                         Map<?, ?> map = (Map<?, ?>) value;
2287                         new JSONObject(map).write(writer, indentFactor, indent);
2288                 } else if (value instanceof Collection) {
2289                         Collection<?> coll = (Collection<?>) value;
2290                         new JSONArray(coll).write(writer, indentFactor, indent);
2291                 } else if (value.getClass().isArray()) {
2292                         new JSONArray(value).write(writer, indentFactor, indent);
2293                 } else {
2294                         quote(value.toString(), writer);
2295                 }
2296                 return writer;
2297         }
2298
2299         static final void indent(Writer writer, int indent) throws IOException {
2300                 for (int i = 0; i < indent; i += 1) {
2301                         writer.write(' ');
2302                 }
2303         }
2304
2305         /**
2306          * Write the contents of the JSONObject as JSON text to a writer.
2307          * 
2308          * <p>
2309          * If <code>indentFactor > 0</code> and the {@link JSONObject} has only one key,
2310          * then the object will be output on a single line:
2311          * 
2312          * <pre>
2313          * {@code {"key": 1}}
2314          * </pre>
2315          * 
2316          * <p>
2317          * If an object has 2 or more keys, then it will be output across multiple
2318          * lines: <code><pre>{
2319          *  "key1": 1,
2320          *  "key2": "value 2",
2321          *  "key3": 3
2322          * }</pre></code>
2323          * <p>
2324          * <b> Warning: This method assumes that the data structure is acyclical. </b>
2325          *
2326          * @param writer       Writes the serialized JSON
2327          * @param indentFactor The number of spaces to add to each level of indentation.
2328          * @param indent       The indentation of the top level.
2329          * @return The writer.
2330          * @throws JSONException
2331          */
2332         public Writer write(Writer writer, int indentFactor, int indent) throws JSONException {
2333                 try {
2334                         boolean commanate = false;
2335                         final int length = this.length();
2336                         writer.write('{');
2337
2338                         if (length == 1) {
2339                                 final Entry<String, ?> entry = this.entrySet().iterator().next();
2340                                 final String key = entry.getKey();
2341                                 writer.write(quote(key));
2342                                 writer.write(':');
2343                                 if (indentFactor > 0) {
2344                                         writer.write(' ');
2345                                 }
2346                                 try {
2347                                         writeValue(writer, entry.getValue(), indentFactor, indent);
2348                                 } catch (Exception e) {
2349                                         throw new JSONException("Unable to write JSONObject value for key: " + key, e);
2350                                 }
2351                         } else if (length != 0) {
2352                                 final int newindent = indent + indentFactor;
2353                                 for (final Entry<String, ?> entry : this.entrySet()) {
2354                                         if (commanate) {
2355                                                 writer.write(',');
2356                                         }
2357                                         if (indentFactor > 0) {
2358                                                 writer.write('\n');
2359                                         }
2360                                         indent(writer, newindent);
2361                                         final String key = entry.getKey();
2362                                         writer.write(quote(key));
2363                                         writer.write(':');
2364                                         if (indentFactor > 0) {
2365                                                 writer.write(' ');
2366                                         }
2367                                         try {
2368                                                 writeValue(writer, entry.getValue(), indentFactor, newindent);
2369                                         } catch (Exception e) {
2370                                                 throw new JSONException("Unable to write JSONObject value for key: " + key, e);
2371                                         }
2372                                         commanate = true;
2373                                 }
2374                                 if (indentFactor > 0) {
2375                                         writer.write('\n');
2376                                 }
2377                                 indent(writer, indent);
2378                         }
2379                         writer.write('}');
2380                         return writer;
2381                 } catch (IOException exception) {
2382                         throw new JSONException(exception);
2383                 }
2384         }
2385
2386         /**
2387          * Returns a java.util.Map containing all of the entries in this object. If an
2388          * entry in the object is a JSONArray or JSONObject it will also be converted.
2389          * <p>
2390          * Warning: This method assumes that the data structure is acyclical.
2391          *
2392          * @return a java.util.Map containing the entries of this object
2393          */
2394         public Map<String, Object> toMap() {
2395                 Map<String, Object> results = new HashMap<String, Object>();
2396                 for (Entry<String, Object> entry : this.entrySet()) {
2397                         Object value;
2398                         if (entry.getValue() == null || NULL.equals(entry.getValue())) {
2399                                 value = null;
2400                         } else if (entry.getValue() instanceof JSONObject) {
2401                                 value = ((JSONObject) entry.getValue()).toMap();
2402                         } else if (entry.getValue() instanceof JSONArray) {
2403                                 value = ((JSONArray) entry.getValue()).toList();
2404                         } else {
2405                                 value = entry.getValue();
2406                         }
2407                         results.put(entry.getKey(), value);
2408                 }
2409                 return results;
2410         }
2411 }