001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software GmbH & Co. KG, please see the 018 * company website: http://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: http://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 * 027 * This file is based on: 028 * org.json.JSONArray 029 * from the JSON in Java implementation. 030 * 031 * Copyright (c) 2002 JSON.org 032 * 033 * Permission is hereby granted, free of charge, to any person obtaining a copy 034 * of this software and associated documentation files (the "Software"), to deal 035 * in the Software without restriction, including without limitation the rights 036 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 037 * copies of the Software, and to permit persons to whom the Software is 038 * furnished to do so, subject to the following conditions: 039 * 040 * The above copyright notice and this permission notice shall be included in all 041 * copies or substantial portions of the Software. 042 * 043 * The Software shall be used for Good, not Evil. 044 * 045 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 046 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 047 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 048 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 049 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 050 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 051 * SOFTWARE. 052 */ 053 054package org.opencms.json; 055 056import java.io.IOException; 057import java.io.Writer; 058import java.lang.reflect.Array; 059import java.util.ArrayList; 060import java.util.Collection; 061import java.util.Iterator; 062import java.util.Map; 063 064/** 065 * A JSONArray is an ordered sequence of values. Its external text form is a 066 * string wrapped in square brackets with commas separating the values. The 067 * internal form is an object having <code>get</code> and <code>opt</code> 068 * methods for accessing the values by index, and <code>put</code> methods for 069 * adding or replacing values. The values can be any of these types: 070 * <code>Boolean</code>, <code>JSONArray</code>, <code>JSONObject</code>, 071 * <code>Number</code>, <code>String</code>, or the 072 * <code>JSONObject.NULL object</code>. 073 * <p> 074 * The constructor can convert a JSON text into a Java object. The 075 * <code>toString</code> method converts to JSON text. 076 * <p> 077 * A <code>get</code> method returns a value if one can be found, and throws an 078 * exception if one cannot be found. An <code>opt</code> method returns a 079 * default value instead of throwing an exception, and so is useful for 080 * obtaining optional values. 081 * <p> 082 * The generic <code>get()</code> and <code>opt()</code> methods return an 083 * object which you can cast or query for type. There are also typed 084 * <code>get</code> and <code>opt</code> methods that do type checking and type 085 * coersion for you. 086 * <p> 087 * The texts produced by the <code>toString</code> methods strictly conform to 088 * JSON syntax rules. The constructors are more forgiving in the texts they will 089 * accept: 090 * <ul> 091 * <li>An extra <code>,</code> <small>(comma)</small> may appear just 092 * before the closing bracket.</li> 093 * <li>The <code>null</code> value will be inserted when there 094 * is <code>,</code> <small>(comma)</small> elision.</li> 095 * <li>Strings may be quoted with <code>'</code> <small>(single 096 * quote)</small>.</li> 097 * <li>Strings do not need to be quoted at all if they do not begin with a quote 098 * or single quote, and if they do not contain leading or trailing spaces, 099 * and if they do not contain any of these characters: 100 * <code>{ } [ ] / \ : , = ; #</code> and if they do not look like numbers 101 * and if they are not the reserved words <code>true</code>, 102 * <code>false</code>, or <code>null</code>.</li> 103 * <li>Values can be separated by <code>;</code> <small>(semicolon)</small> as 104 * well as by <code>,</code> <small>(comma)</small>.</li> 105 * <li>Numbers may have the <code>0-</code> <small>(octal)</small> or 106 * <code>0x-</code> <small>(hex)</small> prefix.</li> 107 * <li>Comments written in the slashshlash, slashstar, and hash conventions 108 * will be ignored.</li> 109 * </ul> 110 111 */ 112public class JSONArray { 113 114 /** 115 * The arrayList where the JSONArray's properties are kept. 116 */ 117 private ArrayList<Object> m_myArrayList; 118 119 /** 120 * Construct an empty JSONArray.<p> 121 */ 122 public JSONArray() { 123 124 m_myArrayList = new ArrayList<Object>(); 125 } 126 127 /** 128 * Construct a JSONArray from a Collection.<p> 129 * 130 * @param collection a Collection. 131 */ 132 public JSONArray(Collection<?> collection) { 133 134 m_myArrayList = (collection == null) ? new ArrayList<Object>() : new ArrayList<Object>(collection); 135 } 136 137 /** 138 * Construct a JSONArray from a collection of beans.<p> 139 * 140 * The collection should have Java Beans.<p> 141 * 142 * @param collection a collection 143 * @param includeSuperClass tell whether to include the super class properties 144 */ 145 146 public JSONArray(Collection<Object> collection, boolean includeSuperClass) { 147 148 m_myArrayList = new ArrayList<Object>(); 149 if (collection != null) { 150 for (Iterator<Object> iter = collection.iterator(); iter.hasNext();) { 151 m_myArrayList.add(new JSONObject(iter.next(), includeSuperClass)); 152 } 153 } 154 } 155 156 /** 157 * Construct a JSONArray from a JSONTokener.<p> 158 * 159 * @param x a JSONTokener 160 * @throws JSONException if there is a syntax error 161 */ 162 public JSONArray(JSONTokener x) 163 throws JSONException { 164 165 this(); 166 char c = x.nextClean(); 167 char q; 168 if (c == '[') { 169 q = ']'; 170 } else if (c == '(') { 171 q = ')'; 172 } else { 173 throw x.syntaxError("A JSONArray text must start with '['"); 174 } 175 if (x.nextClean() == ']') { 176 return; 177 } 178 x.back(); 179 for (;;) { 180 if (x.nextClean() == ',') { 181 x.back(); 182 m_myArrayList.add(null); 183 } else { 184 x.back(); 185 m_myArrayList.add(x.nextValue()); 186 } 187 c = x.nextClean(); 188 switch (c) { 189 case ';': 190 case ',': 191 if (x.nextClean() == ']') { 192 return; 193 } 194 x.back(); 195 break; 196 case ']': 197 case ')': 198 if (q != c) { 199 throw x.syntaxError("Expected a '" + Character.valueOf(q) + "'"); 200 } 201 return; 202 default: 203 throw x.syntaxError("Expected a ',' or ']'"); 204 } 205 } 206 } 207 208 /** 209 * Construct a JSONArray from an array.<p> 210 * 211 * @param array an array 212 * @throws JSONException if not an array 213 */ 214 public JSONArray(Object array) 215 throws JSONException { 216 217 this(); 218 if (array.getClass().isArray()) { 219 int length = Array.getLength(array); 220 for (int i = 0; i < length; i += 1) { 221 this.put(Array.get(array, i)); 222 } 223 } else { 224 throw new JSONException("JSONArray initial value should be a string or collection or array."); 225 } 226 } 227 228 /** 229 * Construct a JSONArray from an array with a bean.<p> 230 * 231 * The array should have Java Beans.<p> 232 * 233 * @param array an array 234 * @param includeSuperClass tell whether to include the super class properties 235 * @throws JSONException if not an array 236 */ 237 public JSONArray(Object array, boolean includeSuperClass) 238 throws JSONException { 239 240 this(); 241 if (array.getClass().isArray()) { 242 int length = Array.getLength(array); 243 for (int i = 0; i < length; i += 1) { 244 this.put(new JSONObject(Array.get(array, i), includeSuperClass)); 245 } 246 } else { 247 throw new JSONException("JSONArray initial value should be a string or collection or array."); 248 } 249 } 250 251 /** 252 * Construct a JSONArray from a source JSON text.<p> 253 * 254 * @param source a string that begins with 255 * <code>[</code> <small>(left bracket)</small> 256 * and ends with <code>]</code> <small>(right bracket)</small> 257 * @throws JSONException if there is a syntax error 258 */ 259 public JSONArray(String source) 260 throws JSONException { 261 262 this(new JSONTokener(source)); 263 } 264 265 /** 266 * Appends values from another JSON array. 267 * 268 * @param array the array whose values should be appended 269 */ 270 public void append(JSONArray array) { 271 272 for (int i = 0; i < array.length(); i++) { 273 put(array.opt(i)); 274 } 275 } 276 277 /** 278 * Check if this array contains the given string value.<p> 279 * 280 * @param value the value to check 281 * 282 * @return <code>true</code> if found, <code>false</code> if not 283 */ 284 public boolean containsString(String value) { 285 286 return m_myArrayList.contains(value); 287 } 288 289 /** 290 * Get the object value associated with an index.<p> 291 * 292 * @param index the index must be between 0 and length() - 1 293 * @return an object value 294 * @throws JSONException if there is no value for the index 295 */ 296 public Object get(int index) throws JSONException { 297 298 Object o = opt(index); 299 if (o == null) { 300 throw new JSONException("JSONArray[" + index + "] not found."); 301 } 302 return o; 303 } 304 305 /** 306 * Get the boolean value associated with an index.<p> 307 * 308 * The string values "true" and "false" are converted to boolean.<p> 309 * 310 * @param index the index must be between 0 and length() - 1 311 * @return the truth 312 * @throws JSONException if there is no value for the index or if the value is not convertable to boolean 313 */ 314 public boolean getBoolean(int index) throws JSONException { 315 316 Object o = get(index); 317 if (o.equals(Boolean.FALSE) || ((o instanceof String) && ((String)o).equalsIgnoreCase("false"))) { 318 return false; 319 } else if (o.equals(Boolean.TRUE) || ((o instanceof String) && ((String)o).equalsIgnoreCase("true"))) { 320 return true; 321 } 322 throw new JSONException("JSONArray[" + index + "] is not a Boolean."); 323 } 324 325 /** 326 * Get the double value associated with an index.<p> 327 * 328 * @param index the index must be between 0 and length() - 1 329 * @return the value 330 * @throws JSONException if the key is not found or if the value cannot be converted to a number 331 */ 332 public double getDouble(int index) throws JSONException { 333 334 Object o = get(index); 335 try { 336 return o instanceof Number ? ((Number)o).doubleValue() : Double.valueOf((String)o).doubleValue(); 337 } catch (Exception e) { 338 throw new JSONException("JSONArray[" + index + "] is not a number."); 339 } 340 } 341 342 /** 343 * Get the int value associated with an index.<p> 344 * 345 * @param index the index must be between 0 and length() - 1 346 * @return the value 347 * @throws JSONException if the key is not found or if the value cannot be converted to a number 348 */ 349 public int getInt(int index) throws JSONException { 350 351 Object o = get(index); 352 return o instanceof Number ? ((Number)o).intValue() : (int)getDouble(index); 353 } 354 355 /** 356 * Get the JSONArray associated with an index.<p> 357 * 358 * @param index the index must be between 0 and length() - 1 359 * @return a JSONArray value 360 * @throws JSONException if there is no value for the index or if the value is not a JSONArray 361 */ 362 public JSONArray getJSONArray(int index) throws JSONException { 363 364 Object o = get(index); 365 if (o instanceof JSONArray) { 366 return (JSONArray)o; 367 } 368 throw new JSONException("JSONArray[" + index + "] is not a JSONArray."); 369 } 370 371 /** 372 * Get the JSONObject associated with an index.<p> 373 * 374 * @param index the index must be between 0 and length() - 1 375 * @return a JSONObject value 376 * @throws JSONException if there is no value for the index or if the value is not a JSONObject 377 */ 378 public JSONObject getJSONObject(int index) throws JSONException { 379 380 Object o = get(index); 381 if (o instanceof JSONObject) { 382 return (JSONObject)o; 383 } 384 throw new JSONException("JSONArray[" + index + "] is not a JSONObject."); 385 } 386 387 /** 388 * Get the long value associated with an index.<p> 389 * 390 * @param index the index must be between 0 and length() - 1 391 * @return the value 392 * @throws JSONException if the key is not found or if the value cannot be converted to a number 393 */ 394 public long getLong(int index) throws JSONException { 395 396 Object o = get(index); 397 return o instanceof Number ? ((Number)o).longValue() : (long)getDouble(index); 398 } 399 400 /** 401 * Get the string associated with an index.<p> 402 * 403 * @param index the index must be between 0 and length() - 1 404 * @return a string value 405 * @throws JSONException if there is no value for the index 406 */ 407 public String getString(int index) throws JSONException { 408 409 return get(index).toString(); 410 } 411 412 /** 413 * Determine if the value is null.<p> 414 * 415 * @param index the index must be between 0 and length() - 1 416 * @return true if the value at the index is null, or if there is no value 417 */ 418 public boolean isNull(int index) { 419 420 return JSONObject.NULL.equals(opt(index)); 421 } 422 423 /** 424 * Make a string from the contents of this JSONArray.<p> 425 * 426 * The <code>separator</code> string is inserted between each element.<p> 427 * 428 * Warning: This method assumes that the data structure is acyclical.<p> 429 * 430 * @param separator a string that will be inserted between the elements 431 * @return a string 432 * @throws JSONException if the array contains an invalid number 433 */ 434 public String join(String separator) throws JSONException { 435 436 int len = length(); 437 StringBuffer sb = new StringBuffer(); 438 439 for (int i = 0; i < len; i += 1) { 440 if (i > 0) { 441 sb.append(separator); 442 } 443 sb.append(JSONObject.valueToString(m_myArrayList.get(i))); 444 } 445 return sb.toString(); 446 } 447 448 /** 449 * Get the number of elements in the JSONArray, included nulls.<p> 450 * 451 * @return the length (or size) 452 */ 453 public int length() { 454 455 return m_myArrayList.size(); 456 } 457 458 /** 459 * Get the optional object value associated with an index.<p> 460 * 461 * @param index the index must be between 0 and length() - 1 462 * @return an object value, or null if there is no object at that index 463 */ 464 public Object opt(int index) { 465 466 return ((index < 0) || (index >= length())) ? null : m_myArrayList.get(index); 467 } 468 469 /** 470 * Get the optional boolean value associated with an index.<p> 471 * 472 * It returns false if there is no value at that index, 473 * or if the value is not Boolean.TRUE or the String "true".<p> 474 * 475 * @param index the index must be between 0 and length() - 1 476 * @return the truth 477 */ 478 public boolean optBoolean(int index) { 479 480 return optBoolean(index, false); 481 } 482 483 /** 484 * Get the optional boolean value associated with an index.<p> 485 * 486 * It returns the defaultValue if there is no value at that index or if 487 * it is not a Boolean or the String "true" or "false" (case insensitive).<p> 488 * 489 * @param index the index must be between 0 and length() - 1 490 * @param defaultValue a boolean default 491 * @return the truth 492 */ 493 public boolean optBoolean(int index, boolean defaultValue) { 494 495 try { 496 return getBoolean(index); 497 } catch (Exception e) { 498 return defaultValue; 499 } 500 } 501 502 /** 503 * Get the optional double value associated with an index.<p> 504 * 505 * NaN is returned if there is no value for the index, 506 * or if the value is not a number and cannot be converted to a number.<p> 507 * 508 * @param index the index must be between 0 and length() - 1 509 * @return the value 510 */ 511 public double optDouble(int index) { 512 513 return optDouble(index, Double.NaN); 514 } 515 516 /** 517 * Get the optional double value associated with an index.<p> 518 * 519 * The defaultValue is returned if there is no value for the index, 520 * or if the value is not a number and cannot be converted to a number.<p> 521 * 522 * @param index the index must be between 0 and length() - 1 523 * @param defaultValue the default value 524 * @return the value 525 */ 526 public double optDouble(int index, double defaultValue) { 527 528 try { 529 return getDouble(index); 530 } catch (Exception e) { 531 return defaultValue; 532 } 533 } 534 535 /** 536 * Get the optional int value associated with an index.<p> 537 * 538 * Zero is returned if there is no value for the index, 539 * or if the value is not a number and cannot be converted to a number.<p> 540 * 541 * @param index the index must be between 0 and length() - 1 542 * @return the value 543 */ 544 public int optInt(int index) { 545 546 return optInt(index, 0); 547 } 548 549 /** 550 * Get the optional int value associated with an index.<p> 551 * 552 * The defaultValue is returned if there is no value for the index, 553 * or if the value is not a number and cannot be converted to a number.<p> 554 * 555 * @param index the index must be between 0 and length() - 1 556 * @param defaultValue the default value 557 * @return the value 558 */ 559 public int optInt(int index, int defaultValue) { 560 561 try { 562 return getInt(index); 563 } catch (Exception e) { 564 return defaultValue; 565 } 566 } 567 568 /** 569 * Get the optional JSONArray associated with an index.<p> 570 * 571 * @param index the index must be between 0 and length() - 1 572 * @return aA JSONArray value, or null if the index has no value, or if the value is not a JSONArray 573 */ 574 public JSONArray optJSONArray(int index) { 575 576 Object o = opt(index); 577 return o instanceof JSONArray ? (JSONArray)o : null; 578 } 579 580 /** 581 * Get the optional JSONObject associated with an index.<p> 582 * 583 * Null is returned if the key is not found, or null if the index has 584 * no value, or if the value is not a JSONObject.<p> 585 * 586 * @param index the index must be between 0 and length() - 1 587 * @return a JSONObject value 588 */ 589 public JSONObject optJSONObject(int index) { 590 591 Object o = opt(index); 592 return o instanceof JSONObject ? (JSONObject)o : null; 593 } 594 595 /** 596 * Get the optional long value associated with an index.<p> 597 * 598 * Zero is returned if there is no value for the index, 599 * or if the value is not a number and cannot be converted to a number.<p> 600 * 601 * @param index the index must be between 0 and length() - 1 602 * @return the value 603 */ 604 public long optLong(int index) { 605 606 return optLong(index, 0); 607 } 608 609 /** 610 * Get the optional long value associated with an index.<p> 611 * 612 * The defaultValue is returned if there is no value for the index, 613 * or if the value is not a number and cannot be converted to a number.<p> 614 * 615 * @param index the index must be between 0 and length() - 1 616 * @param defaultValue the default value 617 * @return the value 618 */ 619 public long optLong(int index, long defaultValue) { 620 621 try { 622 return getLong(index); 623 } catch (Exception e) { 624 return defaultValue; 625 } 626 } 627 628 /** 629 * Get the optional string value associated with an index.<p> 630 * 631 * It returns an empty string if there is no value at that index. If the value 632 * is not a string and is not null, then it is coverted to a string.<p> 633 * 634 * @param index the index must be between 0 and length() - 1 635 * @return a String value 636 */ 637 public String optString(int index) { 638 639 return optString(index, ""); 640 } 641 642 /** 643 * Get the optional string associated with an index.<p> 644 * 645 * The defaultValue is returned if the key is not found.<p> 646 * 647 * @param index tThe index must be between 0 and length() - 1 648 * @param defaultValue the default value 649 * @return a String value 650 */ 651 public String optString(int index, String defaultValue) { 652 653 Object o = opt(index); 654 return o != null ? o.toString() : defaultValue; 655 } 656 657 /** 658 * Append a boolean value. This increases the array's length by one.<p> 659 * 660 * @param value a boolean value 661 * @return this 662 */ 663 public JSONArray put(boolean value) { 664 665 put(value ? Boolean.TRUE : Boolean.FALSE); 666 return this; 667 } 668 669 /** 670 * Put a value in the JSONArray, where the value will be a 671 * JSONArray which is produced from a Collection.<p> 672 * 673 * @param value a Collection value 674 * @return this 675 */ 676 public JSONArray put(Collection<Object> value) { 677 678 put(new JSONArray(value)); 679 return this; 680 } 681 682 /** 683 * Append a double value. This increases the array's length by one.<p> 684 * 685 * @param value a double value 686 * @throws JSONException if the value is not finite 687 * @return this 688 */ 689 public JSONArray put(double value) throws JSONException { 690 691 Double d = Double.valueOf(value); 692 JSONObject.testValidity(d); 693 put(d); 694 return this; 695 } 696 697 /** 698 * Append an int value. This increases the array's length by one.<p> 699 * 700 * @param value an int value 701 * @return this 702 */ 703 public JSONArray put(int value) { 704 705 put(Integer.valueOf(value)); 706 return this; 707 } 708 709 /** 710 * Put or replace a boolean value in the JSONArray. If the index is greater 711 * than the length of the JSONArray, then null elements will be added as 712 * necessary to pad it out.<p> 713 * 714 * @param index the index 715 * @param value a boolean value 716 * @return this 717 * @throws JSONException if the index is negative 718 */ 719 public JSONArray put(int index, boolean value) throws JSONException { 720 721 put(index, value ? Boolean.TRUE : Boolean.FALSE); 722 return this; 723 } 724 725 /** 726 * Put a value in the JSONArray, where the value will be a 727 * JSONArray which is produced from a Collection.<p> 728 * 729 * @param index the index must be between 0 and length() - 1 730 * @param value a Collection value 731 * @return this 732 * @throws JSONException if the index is negative or if the value is 733 * not finite 734 */ 735 public JSONArray put(int index, Collection<Object> value) throws JSONException { 736 737 put(index, new JSONArray(value)); 738 return this; 739 } 740 741 /** 742 * Put or replace a double value. If the index is greater than the length of 743 * the JSONArray, then null elements will be added as necessary to pad 744 * it out.<p> 745 * 746 * @param index the index 747 * @param value a double value 748 * @return this 749 * @throws JSONException if the index is negative or if the value is 750 * not finite 751 */ 752 public JSONArray put(int index, double value) throws JSONException { 753 754 put(index, Double.valueOf(value)); 755 return this; 756 } 757 758 /** 759 * Put or replace an int value. If the index is greater than the length of 760 * the JSONArray, then null elements will be added as necessary to pad 761 * it out.<p> 762 * 763 * @param index the index 764 * @param value an int value 765 * @return this 766 * @throws JSONException if the index is negative 767 */ 768 public JSONArray put(int index, int value) throws JSONException { 769 770 put(index, Integer.valueOf(value)); 771 return this; 772 } 773 774 /** 775 * Put or replace a long value. If the index is greater than the length of 776 * the JSONArray, then null elements will be added as necessary to pad 777 * it out.<p> 778 * 779 * @param index the index 780 * @param value a long value 781 * @return this 782 * @throws JSONException if the index is negative 783 */ 784 public JSONArray put(int index, long value) throws JSONException { 785 786 put(index, Long.valueOf(value)); 787 return this; 788 } 789 790 /** 791 * Put a value in the JSONArray, where the value will be a 792 * JSONObject which is produced from a Map.<p> 793 * 794 * @param index the index must be between 0 and length() - 1 795 * @param value the Map value 796 * @return this 797 * @throws JSONException if the index is negative or if the the value is 798 * an invalid number 799 */ 800 public JSONArray put(int index, Map<?, ?> value) throws JSONException { 801 802 put(index, new JSONObject(value)); 803 return this; 804 } 805 806 /** 807 * Put or replace an object value in the JSONArray. If the index is greater 808 * than the length of the JSONArray, then null elements will be added as 809 * necessary to pad it out.<p> 810 * 811 * @param index the index 812 * @param value the value to put into the array. The value should be a 813 * Boolean, Double, Integer, JSONArray, JSONObject, Long, or String, or the 814 * JSONObject.NULL object 815 * @return this 816 * @throws JSONException if the index is negative or if the the value is 817 * an invalid number 818 */ 819 public JSONArray put(int index, Object value) throws JSONException { 820 821 JSONObject.testValidity(value); 822 if (index < 0) { 823 throw new JSONException("JSONArray[" + index + "] not found."); 824 } 825 if (index < length()) { 826 m_myArrayList.set(index, value); 827 } else { 828 while (index != length()) { 829 put(JSONObject.NULL); 830 } 831 put(value); 832 } 833 return this; 834 } 835 836 /** 837 * Append an long value. This increases the array's length by one.<p> 838 * 839 * @param value a long value 840 * @return this 841 */ 842 public JSONArray put(long value) { 843 844 put(Long.valueOf(value)); 845 return this; 846 } 847 848 /** 849 * Put a value in the JSONArray, where the value will be a 850 * JSONObject which is produced from a Map.<p> 851 * 852 * @param value a Map value 853 * @return this 854 */ 855 public JSONArray put(Map<?, ?> value) { 856 857 put(new JSONObject(value)); 858 return this; 859 } 860 861 /** 862 * Append an object value. This increases the array's length by one.<p> 863 * 864 * @param value an object value. The value should be a 865 * Boolean, Double, Integer, JSONArray, JSONObject, Long, or String, or the 866 * JSONObject.NULL object 867 * @return this 868 */ 869 public JSONArray put(Object value) { 870 871 m_myArrayList.add(value); 872 return this; 873 } 874 875 /** 876 * Produce a JSONObject by combining a JSONArray of names with the values 877 * of this JSONArray.<p> 878 * 879 * @param names a JSONArray containing a list of key strings. These will be 880 * paired with the values 881 * @return a JSONObject, or null if there are no names or if this JSONArray 882 * has no values 883 * @throws JSONException if any of the names are null 884 */ 885 public JSONObject toJSONObject(JSONArray names) throws JSONException { 886 887 if ((names == null) || (names.length() == 0) || (length() == 0)) { 888 return null; 889 } 890 JSONObject jo = new JSONObject(); 891 for (int i = 0; i < names.length(); i += 1) { 892 jo.put(names.getString(i), opt(i)); 893 } 894 return jo; 895 } 896 897 /** 898 * Make a JSON text of this JSONArray.<p> 899 * 900 * For compactness, no unnecessary whitespace is added. If it is not possible to produce a 901 * syntactically correct JSON text then null will be returned instead. This 902 * could occur if the array contains an invalid number.<p> 903 * 904 * Warning: This method assumes that the data structure is acyclical.<p> 905 * 906 * @return a printable, displayable, transmittable representation of the array 907 */ 908 @Override 909 public String toString() { 910 911 try { 912 return '[' + join(",") + ']'; 913 } catch (Exception e) { 914 return null; 915 } 916 } 917 918 /** 919 * Make a pretty printed JSON text of this JSONArray.<p> 920 * 921 * Warning: This method assumes that the data structure is acyclical.<p> 922 * 923 * @param indentFactor the number of spaces to add to each level of 924 * indentation 925 * @return a printable, displayable, transmittable 926 * representation of the object, beginning 927 * with <code>[</code> <small>(left bracket)</small> and ending 928 * with <code>]</code> <small>(right bracket)</small> 929 * @throws JSONException if something goes wrong 930 */ 931 public String toString(int indentFactor) throws JSONException { 932 933 return toString(indentFactor, 0); 934 } 935 936 /** 937 * Write the contents of the JSONArray as JSON text to a writer.<p> 938 * 939 * For compactness, no whitespace is added. 940 * <p> 941 * Warning: This method assumes that the data structure is acyclical.<p> 942 * 943 * @param writer the writer to write the contents to 944 * @return the writer 945 * @throws JSONException if something goes wrong 946 */ 947 public Writer write(Writer writer) throws JSONException { 948 949 try { 950 boolean b = false; 951 int len = length(); 952 953 writer.write('['); 954 955 for (int i = 0; i < len; i += 1) { 956 if (b) { 957 writer.write(','); 958 } 959 Object v = m_myArrayList.get(i); 960 if (v instanceof JSONObject) { 961 ((JSONObject)v).write(writer); 962 } else if (v instanceof JSONArray) { 963 ((JSONArray)v).write(writer); 964 } else { 965 writer.write(JSONObject.valueToString(v)); 966 } 967 b = true; 968 } 969 writer.write(']'); 970 return writer; 971 } catch (IOException e) { 972 throw new JSONException(e); 973 } 974 } 975 976 /** 977 * Make a pretty printed JSON text of this JSONArray.<p> 978 * 979 * Warning: This method assumes that the data structure is acyclical.<p> 980 * 981 * @param indentFactor the number of spaces to add to each level of 982 * indentation 983 * @param indent the indention of the top level 984 * @return a printable, displayable, transmittable 985 * representation of the array 986 * @throws JSONException if something goes wrong 987 */ 988 String toString(int indentFactor, int indent) throws JSONException { 989 990 int len = length(); 991 if (len == 0) { 992 return "[]"; 993 } 994 int i; 995 StringBuffer sb = new StringBuffer("["); 996 if (len == 1) { 997 sb.append(JSONObject.valueToString(m_myArrayList.get(0), indentFactor, indent)); 998 } else { 999 int newindent = indent + indentFactor; 1000 sb.append('\n'); 1001 for (i = 0; i < len; i += 1) { 1002 if (i > 0) { 1003 sb.append(",\n"); 1004 } 1005 for (int j = 0; j < newindent; j += 1) { 1006 sb.append(' '); 1007 } 1008 sb.append(JSONObject.valueToString(m_myArrayList.get(i), indentFactor, newindent)); 1009 } 1010 sb.append('\n'); 1011 for (i = 0; i < indent; i += 1) { 1012 sb.append(' '); 1013 } 1014 } 1015 sb.append(']'); 1016 return sb.toString(); 1017 } 1018}