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