1package org.json; 2 3/* 4Copyright (c) 2002 JSON.org 5 6Permission is hereby granted, free of charge, to any person obtaining a copy 7of this software and associated documentation files (the "Software"), to deal 8in the Software without restriction, including without limitation the rights 9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10copies of the Software, and to permit persons to whom the Software is 11furnished to do so, subject to the following conditions: 12 13The above copyright notice and this permission notice shall be included in all 14copies or substantial portions of the Software. 15 16The Software shall be used for Good, not Evil. 17 18THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24SOFTWARE. 25*/ 26 27import java.util.HashMap; 28import java.util.Iterator; 29import java.util.Map; 30 31// BEGIN android-note 32// - fixed bad htm in javadoc comments -joeo 33// END android-note 34 35/** 36 * A JSONObject is an unordered collection of name/value pairs. Its 37 * external form is a string wrapped in curly braces with colons between the 38 * names and values, and commas between the values and names. The internal form 39 * is an object having <code>get</code> and <code>opt</code> methods for 40 * accessing the values by name, and <code>put</code> methods for adding or 41 * replacing values by name. The values can be any of these types: 42 * <code>Boolean</code>, <code>JSONArray</code>, <code>JSONObject</code>, 43 * <code>Number</code>, <code>String</code>, or the <code>JSONObject.NULL</code> 44 * object. A JSONObject constructor can be used to convert an external form 45 * JSON text into an internal form whose values can be retrieved with the 46 * <code>get</code> and <code>opt</code> methods, or to convert values into a 47 * JSON text using the <code>put</code> and <code>toString</code> methods. 48 * A <code>get</code> method returns a value if one can be found, and throws an 49 * exception if one cannot be found. An <code>opt</code> method returns a 50 * default value instead of throwing an exception, and so is useful for 51 * obtaining optional values. 52 * <p> 53 * The generic <code>get()</code> and <code>opt()</code> methods return an 54 * object, which you can cast or query for type. There are also typed 55 * <code>get</code> and <code>opt</code> methods that do type checking and type 56 * coersion for you. 57 * <p> 58 * The <code>put</code> methods adds values to an object. For example, <pre> 59 * myString = new JSONObject().put("JSON", "Hello, World!").toString();</pre> 60 * produces the string <code>{"JSON": "Hello, World"}</code>. 61 * <p> 62 * The texts produced by the <code>toString</code> methods strictly conform to 63 * the JSON sysntax rules. 64 * The constructors are more forgiving in the texts they will accept: 65 * <ul> 66 * <li>An extra <code>,</code> <small>(comma)</small> may appear just 67 * before the closing brace.</li> 68 * <li>Strings may be quoted with <code>'</code> <small>(single 69 * quote)</small>.</li> 70 * <li>Strings do not need to be quoted at all if they do not begin with a quote 71 * or single quote, and if they do not contain leading or trailing spaces, 72 * and if they do not contain any of these characters: 73 * <code>{ } [ ] / \ : , = ; #</code> and if they do not look like numbers 74 * and if they are not the reserved words <code>true</code>, 75 * <code>false</code>, or <code>null</code>.</li> 76 * <li>Keys can be followed by <code>=</code> or <code>=></code> as well as 77 * by <code>:</code>.</li> 78 * <li>Values can be followed by <code>;</code> <small>(semicolon)</small> as 79 * well as by <code>,</code> <small>(comma)</small>.</li> 80 * <li>Numbers may have the <code>0-</code> <small>(octal)</small> or 81 * <code>0x-</code> <small>(hex)</small> prefix.</li> 82 * <li>Comments written in the slashshlash, slashstar, and hash conventions 83 * will be ignored.</li> 84 * </ul> 85 * @author JSON.org 86 * @version 2 87 */ 88public class JSONObject { 89 90 /** 91 * JSONObject.NULL is equivalent to the value that JavaScript calls null, 92 * whilst Java's null is equivalent to the value that JavaScript calls 93 * undefined. 94 */ 95 private static final class Null { 96 97 /** 98 * There is only intended to be a single instance of the NULL object, 99 * so the clone method returns itself. 100 * @return NULL. 101 */ 102 protected final Object clone() { 103 return this; 104 } 105 106 107 /** 108 * A Null object is equal to the null value and to itself. 109 * @param object An object to test for nullness. 110 * @return true if the object parameter is the JSONObject.NULL object 111 * or null. 112 */ 113 public boolean equals(Object object) { 114 return object == null || object == this; 115 } 116 117 118 /** 119 * Get the "null" string value. 120 * @return The string "null". 121 */ 122 public String toString() { 123 return "null"; 124 } 125 } 126 127 128 /** 129 * The hash map where the JSONObject's properties are kept. 130 */ 131 private HashMap myHashMap; 132 133 134 /** 135 * It is sometimes more convenient and less ambiguous to have a 136 * <code>NULL</code> object than to use Java's <code>null</code> value. 137 * <code>JSONObject.NULL.equals(null)</code> returns <code>true</code>. 138 * <code>JSONObject.NULL.toString()</code> returns <code>"null"</code>. 139 */ 140 public static final Object NULL = new Null(); 141 142 143 /** 144 * Construct an empty JSONObject. 145 */ 146 public JSONObject() { 147 this.myHashMap = new HashMap(); 148 } 149 150 151 /** 152 * Construct a JSONObject from a subset of another JSONObject. 153 * An array of strings is used to identify the keys that should be copied. 154 * Missing keys are ignored. 155 * @param jo A JSONObject. 156 * @param sa An array of strings. 157 * @exception JSONException If a value is a non-finite number. 158 */ 159 public JSONObject(JSONObject jo, String[] sa) throws JSONException { 160 this(); 161 for (int i = 0; i < sa.length; i += 1) { 162 putOpt(sa[i], jo.opt(sa[i])); 163 } 164 } 165 166 167 /** 168 * Construct a JSONObject from a JSONTokener. 169 * @param x A JSONTokener object containing the source string. 170 * @throws JSONException If there is a syntax error in the source string. 171 */ 172 public JSONObject(JSONTokener x) throws JSONException { 173 this(); 174 char c; 175 String key; 176 177 if (x.nextClean() != '{') { 178 throw x.syntaxError("A JSONObject text must begin with '{'"); 179 } 180 for (;;) { 181 c = x.nextClean(); 182 switch (c) { 183 case 0: 184 throw x.syntaxError("A JSONObject text must end with '}'"); 185 case '}': 186 return; 187 default: 188 x.back(); 189 key = x.nextValue().toString(); 190 } 191 192 /* 193 * The key is followed by ':'. We will also tolerate '=' or '=>'. 194 */ 195 196 c = x.nextClean(); 197 if (c == '=') { 198 if (x.next() != '>') { 199 x.back(); 200 } 201 } else if (c != ':') { 202 throw x.syntaxError("Expected a ':' after a key"); 203 } 204 this.myHashMap.put(key, x.nextValue()); 205 206 /* 207 * Pairs are separated by ','. We will also tolerate ';'. 208 */ 209 210 switch (x.nextClean()) { 211 case ';': 212 case ',': 213 if (x.nextClean() == '}') { 214 return; 215 } 216 x.back(); 217 break; 218 case '}': 219 return; 220 default: 221 throw x.syntaxError("Expected a ',' or '}'"); 222 } 223 } 224 } 225 226 227 /** 228 * Construct a JSONObject from a Map. 229 * @param map A map object that can be used to initialize the contents of 230 * the JSONObject. 231 */ 232 public JSONObject(Map map) { 233 this.myHashMap = new HashMap(map); 234 } 235 236 237 /** 238 * Construct a JSONObject from a string. 239 * This is the most commonly used JSONObject constructor. 240 * @param string A string beginning 241 * with <code>{</code> <small>(left brace)</small> and ending 242 * with <code>}</code> <small>(right brace)</small>. 243 * @exception JSONException If there is a syntax error in the source string. 244 */ 245 public JSONObject(String string) throws JSONException { 246 this(new JSONTokener(string)); 247 } 248 249 250 /** 251 * Accumulate values under a key. It is similar to the put method except 252 * that if there is already an object stored under the key then a 253 * JSONArray is stored under the key to hold all of the accumulated values. 254 * If there is already a JSONArray, then the new value is appended to it. 255 * In contrast, the put method replaces the previous value. 256 * @param key A key string. 257 * @param value An object to be accumulated under the key. 258 * @return this. 259 * @throws JSONException If the value is an invalid number 260 * or if the key is null. 261 */ 262 public JSONObject accumulate(String key, Object value) 263 throws JSONException { 264 testValidity(value); 265 Object o = opt(key); 266 if (o == null) { 267 put(key, value); 268 } else if (o instanceof JSONArray) { 269 ((JSONArray)o).put(value); 270 } else { 271 put(key, new JSONArray().put(o).put(value)); 272 } 273 return this; 274 } 275 276 277 /** 278 * Get the value object associated with a key. 279 * 280 * @param key A key string. 281 * @return The object associated with the key. 282 * @throws JSONException if the key is not found. 283 */ 284 public Object get(String key) throws JSONException { 285 Object o = opt(key); 286 if (o == null) { 287 throw new JSONException("JSONObject[" + quote(key) + 288 "] not found."); 289 } 290 return o; 291 } 292 293 294 /** 295 * Get the boolean value associated with a key. 296 * 297 * @param key A key string. 298 * @return The truth. 299 * @throws JSONException 300 * if the value is not a Boolean or the String "true" or "false". 301 */ 302 public boolean getBoolean(String key) throws JSONException { 303 Object o = get(key); 304 if (o.equals(Boolean.FALSE) || 305 (o instanceof String && 306 ((String)o).equalsIgnoreCase("false"))) { 307 return false; 308 } else if (o.equals(Boolean.TRUE) || 309 (o instanceof String && 310 ((String)o).equalsIgnoreCase("true"))) { 311 return true; 312 } 313 throw new JSONException("JSONObject[" + quote(key) + 314 "] is not a Boolean."); 315 } 316 317 318 /** 319 * Get the double value associated with a key. 320 * @param key A key string. 321 * @return The numeric value. 322 * @throws JSONException if the key is not found or 323 * if the value is not a Number object and cannot be converted to a number. 324 */ 325 public double getDouble(String key) throws JSONException { 326 Object o = get(key); 327 try { 328 return o instanceof Number ? 329 ((Number)o).doubleValue() : Double.parseDouble((String)o); 330 } catch (Exception e) { 331 throw new JSONException("JSONObject[" + quote(key) + 332 "] is not a number."); 333 } 334 } 335 336 337 /** 338 * Get the int value associated with a key. If the number value is too 339 * large for an int, it will be clipped. 340 * 341 * @param key A key string. 342 * @return The integer value. 343 * @throws JSONException if the key is not found or if the value cannot 344 * be converted to an integer. 345 */ 346 public int getInt(String key) throws JSONException { 347 Object o = get(key); 348 return o instanceof Number ? 349 ((Number)o).intValue() : (int)getDouble(key); 350 } 351 352 353 /** 354 * Get the JSONArray value associated with a key. 355 * 356 * @param key A key string. 357 * @return A JSONArray which is the value. 358 * @throws JSONException if the key is not found or 359 * if the value is not a JSONArray. 360 */ 361 public JSONArray getJSONArray(String key) throws JSONException { 362 Object o = get(key); 363 if (o instanceof JSONArray) { 364 return (JSONArray)o; 365 } 366 throw new JSONException("JSONObject[" + quote(key) + 367 "] is not a JSONArray."); 368 } 369 370 371 /** 372 * Get the JSONObject value associated with a key. 373 * 374 * @param key A key string. 375 * @return A JSONObject which is the value. 376 * @throws JSONException if the key is not found or 377 * if the value is not a JSONObject. 378 */ 379 public JSONObject getJSONObject(String key) throws JSONException { 380 Object o = get(key); 381 if (o instanceof JSONObject) { 382 return (JSONObject)o; 383 } 384 throw new JSONException("JSONObject[" + quote(key) + 385 "] is not a JSONObject."); 386 } 387 388 389 /** 390 * Get the long value associated with a key. If the number value is too 391 * long for a long, it will be clipped. 392 * 393 * @param key A key string. 394 * @return The long value. 395 * @throws JSONException if the key is not found or if the value cannot 396 * be converted to a long. 397 */ 398 public long getLong(String key) throws JSONException { 399 Object o = get(key); 400 return o instanceof Number ? 401 ((Number)o).longValue() : (long)getDouble(key); 402 } 403 404 405 /** 406 * Get the string associated with a key. 407 * 408 * @param key A key string. 409 * @return A string which is the value. 410 * @throws JSONException if the key is not found. 411 */ 412 public String getString(String key) throws JSONException { 413 return get(key).toString(); 414 } 415 416 417 /** 418 * Determine if the JSONObject contains a specific key. 419 * @param key A key string. 420 * @return true if the key exists in the JSONObject. 421 */ 422 public boolean has(String key) { 423 return this.myHashMap.containsKey(key); 424 } 425 426 427 /** 428 * Determine if the value associated with the key is null or if there is 429 * no value. 430 * @param key A key string. 431 * @return true if there is no value associated with the key or if 432 * the value is the JSONObject.NULL object. 433 */ 434 public boolean isNull(String key) { 435 return JSONObject.NULL.equals(opt(key)); 436 } 437 438 439 /** 440 * Get an enumeration of the keys of the JSONObject. 441 * 442 * @return An iterator of the keys. 443 */ 444 public Iterator keys() { 445 return this.myHashMap.keySet().iterator(); 446 } 447 448 449 /** 450 * Get the number of keys stored in the JSONObject. 451 * 452 * @return The number of keys in the JSONObject. 453 */ 454 public int length() { 455 return this.myHashMap.size(); 456 } 457 458 459 /** 460 * Produce a JSONArray containing the names of the elements of this 461 * JSONObject. 462 * @return A JSONArray containing the key strings, or null if the JSONObject 463 * is empty. 464 */ 465 public JSONArray names() { 466 JSONArray ja = new JSONArray(); 467 Iterator keys = keys(); 468 while (keys.hasNext()) { 469 ja.put(keys.next()); 470 } 471 return ja.length() == 0 ? null : ja; 472 } 473 474 /** 475 * Produce a string from a number. 476 * @param n A Number 477 * @return A String. 478 * @throws JSONException If n is a non-finite number. 479 */ 480 static public String numberToString(Number n) 481 throws JSONException { 482 if (n == null) { 483 throw new JSONException("Null pointer"); 484 } 485 testValidity(n); 486 487// Shave off trailing zeros and decimal point, if possible. 488 489 String s = n.toString(); 490 if (s.indexOf('.') > 0 && s.indexOf('e') < 0 && s.indexOf('E') < 0) { 491 while (s.endsWith("0")) { 492 s = s.substring(0, s.length() - 1); 493 } 494 if (s.endsWith(".")) { 495 s = s.substring(0, s.length() - 1); 496 } 497 } 498 return s; 499 } 500 501 502 /** 503 * Get an optional value associated with a key. 504 * @param key A key string. 505 * @return An object which is the value, or null if there is no value. 506 */ 507 public Object opt(String key) { 508 return key == null ? null : this.myHashMap.get(key); 509 } 510 511 512 /** 513 * Get an optional boolean associated with a key. 514 * It returns false if there is no such key, or if the value is not 515 * Boolean.TRUE or the String "true". 516 * 517 * @param key A key string. 518 * @return The truth. 519 */ 520 public boolean optBoolean(String key) { 521 return optBoolean(key, false); 522 } 523 524 525 /** 526 * Get an optional boolean associated with a key. 527 * It returns the defaultValue if there is no such key, or if it is not 528 * a Boolean or the String "true" or "false" (case insensitive). 529 * 530 * @param key A key string. 531 * @param defaultValue The default. 532 * @return The truth. 533 */ 534 public boolean optBoolean(String key, boolean defaultValue) { 535 try { 536 return getBoolean(key); 537 } catch (Exception e) { 538 return defaultValue; 539 } 540 } 541 542 543 /** 544 * Get an optional double associated with a key, 545 * or NaN if there is no such key or if its value is not a number. 546 * If the value is a string, an attempt will be made to evaluate it as 547 * a number. 548 * 549 * @param key A string which is the key. 550 * @return An object which is the value. 551 */ 552 public double optDouble(String key) { 553 return optDouble(key, Double.NaN); 554 } 555 556 557 /** 558 * Get an optional double associated with a key, or the 559 * defaultValue if there is no such key or if its value is not a number. 560 * If the value is a string, an attempt will be made to evaluate it as 561 * a number. 562 * 563 * @param key A key string. 564 * @param defaultValue The default. 565 * @return An object which is the value. 566 */ 567 public double optDouble(String key, double defaultValue) { 568 try { 569 Object o = opt(key); 570 return o instanceof Number ? ((Number)o).doubleValue() : 571 new Double((String)o).doubleValue(); 572 } catch (Exception e) { 573 return defaultValue; 574 } 575 } 576 577 578 /** 579 * Get an optional int value associated with a key, 580 * or zero if there is no such key or if the value is not a number. 581 * If the value is a string, an attempt will be made to evaluate it as 582 * a number. 583 * 584 * @param key A key string. 585 * @return An object which is the value. 586 */ 587 public int optInt(String key) { 588 return optInt(key, 0); 589 } 590 591 592 /** 593 * Get an optional int value associated with a key, 594 * or the default if there is no such key or if the value is not a number. 595 * If the value is a string, an attempt will be made to evaluate it as 596 * a number. 597 * 598 * @param key A key string. 599 * @param defaultValue The default. 600 * @return An object which is the value. 601 */ 602 public int optInt(String key, int defaultValue) { 603 try { 604 return getInt(key); 605 } catch (Exception e) { 606 return defaultValue; 607 } 608 } 609 610 611 /** 612 * Get an optional JSONArray associated with a key. 613 * It returns null if there is no such key, or if its value is not a 614 * JSONArray. 615 * 616 * @param key A key string. 617 * @return A JSONArray which is the value. 618 */ 619 public JSONArray optJSONArray(String key) { 620 Object o = opt(key); 621 return o instanceof JSONArray ? (JSONArray)o : null; 622 } 623 624 625 /** 626 * Get an optional JSONObject associated with a key. 627 * It returns null if there is no such key, or if its value is not a 628 * JSONObject. 629 * 630 * @param key A key string. 631 * @return A JSONObject which is the value. 632 */ 633 public JSONObject optJSONObject(String key) { 634 Object o = opt(key); 635 return o instanceof JSONObject ? (JSONObject)o : null; 636 } 637 638 639 /** 640 * Get an optional long value associated with a key, 641 * or zero if there is no such key or if the value is not a number. 642 * If the value is a string, an attempt will be made to evaluate it as 643 * a number. 644 * 645 * @param key A key string. 646 * @return An object which is the value. 647 */ 648 public long optLong(String key) { 649 return optLong(key, 0); 650 } 651 652 653 /** 654 * Get an optional long value associated with a key, 655 * or the default if there is no such key or if the value is not a number. 656 * If the value is a string, an attempt will be made to evaluate it as 657 * a number. 658 * 659 * @param key A key string. 660 * @param defaultValue The default. 661 * @return An object which is the value. 662 */ 663 public long optLong(String key, long defaultValue) { 664 try { 665 return getLong(key); 666 } catch (Exception e) { 667 return defaultValue; 668 } 669 } 670 671 672 /** 673 * Get an optional string associated with a key. 674 * It returns an empty string if there is no such key. If the value is not 675 * a string and is not null, then it is coverted to a string. 676 * 677 * @param key A key string. 678 * @return A string which is the value. 679 */ 680 public String optString(String key) { 681 return optString(key, ""); 682 } 683 684 685 /** 686 * Get an optional string associated with a key. 687 * It returns the defaultValue if there is no such key. 688 * 689 * @param key A key string. 690 * @param defaultValue The default. 691 * @return A string which is the value. 692 */ 693 public String optString(String key, String defaultValue) { 694 Object o = opt(key); 695 return o != null ? o.toString() : defaultValue; 696 } 697 698 699 /** 700 * Put a key/boolean pair in the JSONObject. 701 * 702 * @param key A key string. 703 * @param value A boolean which is the value. 704 * @return this. 705 * @throws JSONException If the key is null. 706 */ 707 public JSONObject put(String key, boolean value) throws JSONException { 708 put(key, Boolean.valueOf(value)); 709 return this; 710 } 711 712 713 /** 714 * Put a key/double pair in the JSONObject. 715 * 716 * @param key A key string. 717 * @param value A double which is the value. 718 * @return this. 719 * @throws JSONException If the key is null or if the number is invalid. 720 */ 721 public JSONObject put(String key, double value) throws JSONException { 722 put(key, new Double(value)); 723 return this; 724 } 725 726 727 /** 728 * Put a key/int pair in the JSONObject. 729 * 730 * @param key A key string. 731 * @param value An int which is the value. 732 * @return this. 733 * @throws JSONException If the key is null. 734 */ 735 public JSONObject put(String key, int value) throws JSONException { 736 put(key, new Integer(value)); 737 return this; 738 } 739 740 741 /** 742 * Put a key/long pair in the JSONObject. 743 * 744 * @param key A key string. 745 * @param value A long which is the value. 746 * @return this. 747 * @throws JSONException If the key is null. 748 */ 749 public JSONObject put(String key, long value) throws JSONException { 750 put(key, new Long(value)); 751 return this; 752 } 753 754 755 /** 756 * Put a key/value pair in the JSONObject. If the value is null, 757 * then the key will be removed from the JSONObject if it is present. 758 * @param key A key string. 759 * @param value An object which is the value. It should be of one of these 760 * types: Boolean, Double, Integer, JSONArray, JSONObject, Long, String, 761 * or the JSONObject.NULL object. 762 * @return this. 763 * @throws JSONException If the value is non-finite number 764 * or if the key is null. 765 */ 766 public JSONObject put(String key, Object value) 767 throws JSONException { 768 if (key == null) { 769 throw new JSONException("Null key."); 770 } 771 if (value != null) { 772 testValidity(value); 773 this.myHashMap.put(key, value); 774 } else { 775 remove(key); 776 } 777 return this; 778 } 779 780 781 /** 782 * Put a key/value pair in the JSONObject, but only if the 783 * key and the value are both non-null. 784 * @param key A key string. 785 * @param value An object which is the value. It should be of one of these 786 * types: Boolean, Double, Integer, JSONArray, JSONObject, Long, String, 787 * or the JSONObject.NULL object. 788 * @return this. 789 * @throws JSONException If the value is a non-finite number. 790 */ 791 public JSONObject putOpt(String key, Object value) throws JSONException { 792 if (key != null && value != null) { 793 put(key, value); 794 } 795 return this; 796 } 797 798 799 /** 800 * Produce a string in double quotes with backslash sequences in all the 801 * right places. A backslash will be inserted within </, allowing JSON 802 * text to be delivered in HTML. In JSON text, a string cannot contain a 803 * control character or an unescaped quote or backslash. 804 * @param string A String 805 * @return A String correctly formatted for insertion in a JSON text. 806 */ 807 public static String quote(String string) { 808 if (string == null || string.length() == 0) { 809 return "\"\""; 810 } 811 812 char b; 813 char c = 0; 814 int i; 815 int len = string.length(); 816 StringBuilder sb = new StringBuilder(len + 4); 817 String t; 818 819 sb.append('"'); 820 for (i = 0; i < len; i += 1) { 821 b = c; 822 c = string.charAt(i); 823 switch (c) { 824 case '\\': 825 case '"': 826 sb.append('\\'); 827 sb.append(c); 828 break; 829 case '/': 830 if (b == '<') { 831 sb.append('\\'); 832 } 833 sb.append(c); 834 break; 835 case '\b': 836 sb.append("\\b"); 837 break; 838 case '\t': 839 sb.append("\\t"); 840 break; 841 case '\n': 842 sb.append("\\n"); 843 break; 844 case '\f': 845 sb.append("\\f"); 846 break; 847 case '\r': 848 sb.append("\\r"); 849 break; 850 default: 851 if (c < ' ') { 852 t = "000" + Integer.toHexString(c); 853 sb.append("\\u" + t.substring(t.length() - 4)); 854 } else { 855 sb.append(c); 856 } 857 } 858 } 859 sb.append('"'); 860 return sb.toString(); 861 } 862 863 /** 864 * Remove a name and its value, if present. 865 * @param key The name to be removed. 866 * @return The value that was associated with the name, 867 * or null if there was no value. 868 */ 869 public Object remove(String key) { 870 return this.myHashMap.remove(key); 871 } 872 873 /** 874 * Throw an exception if the object is an NaN or infinite number. 875 * @param o The object to test. 876 * @throws JSONException If o is a non-finite number. 877 */ 878 static void testValidity(Object o) throws JSONException { 879 if (o != null) { 880 if (o instanceof Double) { 881 if (((Double)o).isInfinite() || ((Double)o).isNaN()) { 882 throw new JSONException( 883 "JSON does not allow non-finite numbers"); 884 } 885 } else if (o instanceof Float) { 886 if (((Float)o).isInfinite() || ((Float)o).isNaN()) { 887 throw new JSONException( 888 "JSON does not allow non-finite numbers."); 889 } 890 } 891 } 892 } 893 894 895 /** 896 * Produce a JSONArray containing the values of the members of this 897 * JSONObject. 898 * @param names A JSONArray containing a list of key strings. This 899 * determines the sequence of the values in the result. 900 * @return A JSONArray of values. 901 * @throws JSONException If any of the values are non-finite numbers. 902 */ 903 public JSONArray toJSONArray(JSONArray names) throws JSONException { 904 if (names == null || names.length() == 0) { 905 return null; 906 } 907 JSONArray ja = new JSONArray(); 908 for (int i = 0; i < names.length(); i += 1) { 909 ja.put(this.opt(names.getString(i))); 910 } 911 return ja; 912 } 913 914 /** 915 * Make an JSON text of this JSONObject. For compactness, no whitespace 916 * is added. If this would not result in a syntactically correct JSON text, 917 * then null will be returned instead. 918 * <p> 919 * Warning: This method assumes that the data structure is acyclical. 920 * 921 * @return a printable, displayable, portable, transmittable 922 * representation of the object, beginning 923 * with <code>{</code> <small>(left brace)</small> and ending 924 * with <code>}</code> <small>(right brace)</small>. 925 */ 926 public String toString() { 927 try { 928 Iterator keys = keys(); 929 StringBuilder sb = new StringBuilder("{"); 930 931 while (keys.hasNext()) { 932 if (sb.length() > 1) { 933 sb.append(','); 934 } 935 Object o = keys.next(); 936 sb.append(quote(o.toString())); 937 sb.append(':'); 938 sb.append(valueToString(this.myHashMap.get(o))); 939 } 940 sb.append('}'); 941 return sb.toString(); 942 } catch (Exception e) { 943 return null; 944 } 945 } 946 947 948 /** 949 * Make a prettyprinted JSON text of this JSONObject. 950 * <p> 951 * Warning: This method assumes that the data structure is acyclical. 952 * @param indentFactor The number of spaces to add to each level of 953 * indentation. 954 * @return a printable, displayable, portable, transmittable 955 * representation of the object, beginning 956 * with <code>{</code> <small>(left brace)</small> and ending 957 * with <code>}</code> <small>(right brace)</small>. 958 * @throws JSONException If the object contains an invalid number. 959 */ 960 public String toString(int indentFactor) throws JSONException { 961 return toString(indentFactor, 0); 962 } 963 964 965 /** 966 * Make a prettyprinted JSON text of this JSONObject. 967 * <p> 968 * Warning: This method assumes that the data structure is acyclical. 969 * @param indentFactor The number of spaces to add to each level of 970 * indentation. 971 * @param indent The indentation of the top level. 972 * @return a printable, displayable, transmittable 973 * representation of the object, beginning 974 * with <code>{</code> <small>(left brace)</small> and ending 975 * with <code>}</code> <small>(right brace)</small>. 976 * @throws JSONException If the object contains an invalid number. 977 */ 978 String toString(int indentFactor, int indent) throws JSONException { 979 int i; 980 int n = length(); 981 if (n == 0) { 982 return "{}"; 983 } 984 Iterator keys = keys(); 985 StringBuilder sb = new StringBuilder("{"); 986 int newindent = indent + indentFactor; 987 Object o; 988 if (n == 1) { 989 o = keys.next(); 990 sb.append(quote(o.toString())); 991 sb.append(": "); 992 sb.append(valueToString(this.myHashMap.get(o), indentFactor, 993 indent)); 994 } else { 995 while (keys.hasNext()) { 996 o = keys.next(); 997 if (sb.length() > 1) { 998 sb.append(",\n"); 999 } else { 1000 sb.append('\n'); 1001 } 1002 for (i = 0; i < newindent; i += 1) { 1003 sb.append(' '); 1004 } 1005 sb.append(quote(o.toString())); 1006 sb.append(": "); 1007 sb.append(valueToString(this.myHashMap.get(o), indentFactor, 1008 newindent)); 1009 } 1010 if (sb.length() > 1) { 1011 sb.append('\n'); 1012 for (i = 0; i < indent; i += 1) { 1013 sb.append(' '); 1014 } 1015 } 1016 } 1017 sb.append('}'); 1018 return sb.toString(); 1019 } 1020 1021 1022 /** 1023 * Make a JSON text of an object value. 1024 * <p> 1025 * Warning: This method assumes that the data structure is acyclical. 1026 * @param value The value to be serialized. 1027 * @return a printable, displayable, transmittable 1028 * representation of the object, beginning 1029 * with <code>{</code> <small>(left brace)</small> and ending 1030 * with <code>}</code> <small>(right brace)</small>. 1031 * @throws JSONException If the value is or contains an invalid number. 1032 */ 1033 static String valueToString(Object value) throws JSONException { 1034 if (value == null || value.equals(null)) { 1035 return "null"; 1036 } 1037 if (value instanceof Number) { 1038 return numberToString((Number) value); 1039 } 1040 if (value instanceof Boolean || value instanceof JSONObject || 1041 value instanceof JSONArray) { 1042 return value.toString(); 1043 } 1044 return quote(value.toString()); 1045 } 1046 1047 1048 /** 1049 * Make a prettyprinted JSON text of an object value. 1050 * <p> 1051 * Warning: This method assumes that the data structure is acyclical. 1052 * @param value The value to be serialized. 1053 * @param indentFactor The number of spaces to add to each level of 1054 * indentation. 1055 * @param indent The indentation of the top level. 1056 * @return a printable, displayable, transmittable 1057 * representation of the object, beginning 1058 * with <code>{</code> <small>(left brace)</small> and ending 1059 * with <code>}</code> <small>(right brace)</small>. 1060 * @throws JSONException If the object contains an invalid number. 1061 */ 1062 static String valueToString(Object value, int indentFactor, int indent) 1063 throws JSONException { 1064 if (value == null || value.equals(null)) { 1065 return "null"; 1066 } 1067 if (value instanceof Number) { 1068 return numberToString((Number) value); 1069 } 1070 if (value instanceof Boolean) { 1071 return value.toString(); 1072 } 1073 if (value instanceof JSONObject) { 1074 return ((JSONObject)value).toString(indentFactor, indent); 1075 } 1076 if (value instanceof JSONArray) { 1077 return ((JSONArray)value).toString(indentFactor, indent); 1078 } 1079 return quote(value.toString()); 1080 } 1081} 1082