1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package org.json; 18 19import java.math.BigDecimal; 20import java.math.BigInteger; 21import java.util.ArrayList; 22import java.util.Arrays; 23import java.util.Collection; 24import java.util.Collections; 25import java.util.HashMap; 26import java.util.HashSet; 27import java.util.Iterator; 28import java.util.Map; 29import java.util.NoSuchElementException; 30import java.util.Set; 31import java.util.TreeMap; 32import junit.framework.TestCase; 33 34/** 35 * This black box test was written without inspecting the non-free org.json sourcecode. 36 */ 37public class JSONObjectTest extends TestCase { 38 39 public void testEmptyObject() throws JSONException { 40 JSONObject object = new JSONObject(); 41 assertEquals(0, object.length()); 42 43 // bogus (but documented) behaviour: returns null rather than the empty object! 44 assertNull(object.names()); 45 46 // returns null rather than an empty array! 47 assertNull(object.toJSONArray(new JSONArray())); 48 assertEquals("{}", object.toString()); 49 assertEquals("{}", object.toString(5)); 50 try { 51 object.get("foo"); 52 fail(); 53 } catch (JSONException e) { 54 } 55 try { 56 object.getBoolean("foo"); 57 fail(); 58 } catch (JSONException e) { 59 } 60 try { 61 object.getDouble("foo"); 62 fail(); 63 } catch (JSONException e) { 64 } 65 try { 66 object.getInt("foo"); 67 fail(); 68 } catch (JSONException e) { 69 } 70 try { 71 object.getJSONArray("foo"); 72 fail(); 73 } catch (JSONException e) { 74 } 75 try { 76 object.getJSONObject("foo"); 77 fail(); 78 } catch (JSONException e) { 79 } 80 try { 81 object.getLong("foo"); 82 fail(); 83 } catch (JSONException e) { 84 } 85 try { 86 object.getString("foo"); 87 fail(); 88 } catch (JSONException e) { 89 } 90 assertFalse(object.has("foo")); 91 assertTrue(object.isNull("foo")); // isNull also means "is not present" 92 assertNull(object.opt("foo")); 93 assertEquals(false, object.optBoolean("foo")); 94 assertEquals(true, object.optBoolean("foo", true)); 95 assertEquals(Double.NaN, object.optDouble("foo")); 96 assertEquals(5.0, object.optDouble("foo", 5.0)); 97 assertEquals(0, object.optInt("foo")); 98 assertEquals(5, object.optInt("foo", 5)); 99 assertEquals(null, object.optJSONArray("foo")); 100 assertEquals(null, object.optJSONObject("foo")); 101 assertEquals(0, object.optLong("foo")); 102 assertEquals(Long.MAX_VALUE-1, object.optLong("foo", Long.MAX_VALUE-1)); 103 assertEquals("", object.optString("foo")); // empty string is default! 104 assertEquals("bar", object.optString("foo", "bar")); 105 assertNull(object.remove("foo")); 106 } 107 108 public void testEqualsAndHashCode() throws JSONException { 109 JSONObject a = new JSONObject(); 110 JSONObject b = new JSONObject(); 111 112 // JSON object doesn't override either equals or hashCode (!) 113 assertFalse(a.equals(b)); 114 assertEquals(a.hashCode(), System.identityHashCode(a)); 115 } 116 117 public void testGet() throws JSONException { 118 JSONObject object = new JSONObject(); 119 Object value = new Object(); 120 object.put("foo", value); 121 object.put("bar", new Object()); 122 object.put("baz", new Object()); 123 assertSame(value, object.get("foo")); 124 try { 125 object.get("FOO"); 126 fail(); 127 } catch (JSONException e) { 128 } 129 try { 130 object.put(null, value); 131 fail(); 132 } catch (JSONException e) { 133 } 134 try { 135 object.get(null); 136 fail(); 137 } catch (JSONException e) { 138 } 139 } 140 141 public void testPut() throws JSONException { 142 JSONObject object = new JSONObject(); 143 assertSame(object, object.put("foo", true)); 144 object.put("foo", false); 145 assertEquals(false, object.get("foo")); 146 147 object.put("foo", 5.0d); 148 assertEquals(5.0d, object.get("foo")); 149 object.put("foo", 0); 150 assertEquals(0, object.get("foo")); 151 object.put("bar", Long.MAX_VALUE - 1); 152 assertEquals(Long.MAX_VALUE - 1, object.get("bar")); 153 object.put("baz", "x"); 154 assertEquals("x", object.get("baz")); 155 object.put("bar", JSONObject.NULL); 156 assertSame(JSONObject.NULL, object.get("bar")); 157 } 158 159 public void testPutNullRemoves() throws JSONException { 160 JSONObject object = new JSONObject(); 161 object.put("foo", "bar"); 162 object.put("foo", (Collection) null); 163 assertEquals(0, object.length()); 164 assertFalse(object.has("foo")); 165 try { 166 object.get("foo"); 167 fail(); 168 } catch (JSONException e) { 169 } 170 } 171 172 public void testPutOpt() throws JSONException { 173 JSONObject object = new JSONObject(); 174 object.put("foo", "bar"); 175 object.putOpt("foo", null); 176 assertEquals("bar", object.get("foo")); 177 object.putOpt(null, null); 178 assertEquals(1, object.length()); 179 object.putOpt(null, "bar"); 180 assertEquals(1, object.length()); 181 } 182 183 public void testPutOptUnsupportedNumbers() throws JSONException { 184 JSONObject object = new JSONObject(); 185 try { 186 object.putOpt("foo", Double.NaN); 187 fail(); 188 } catch (JSONException e) { 189 } 190 try { 191 object.putOpt("foo", Double.NEGATIVE_INFINITY); 192 fail(); 193 } catch (JSONException e) { 194 } 195 try { 196 object.putOpt("foo", Double.POSITIVE_INFINITY); 197 fail(); 198 } catch (JSONException e) { 199 } 200 } 201 202 public void testRemove() throws JSONException { 203 JSONObject object = new JSONObject(); 204 object.put("foo", "bar"); 205 assertEquals(null, object.remove(null)); 206 assertEquals(null, object.remove("")); 207 assertEquals(null, object.remove("bar")); 208 assertEquals("bar", object.remove("foo")); 209 assertEquals(null, object.remove("foo")); 210 } 211 212 public void testBooleans() throws JSONException { 213 JSONObject object = new JSONObject(); 214 object.put("foo", true); 215 object.put("bar", false); 216 object.put("baz", "true"); 217 object.put("quux", "false"); 218 assertEquals(4, object.length()); 219 assertEquals(true, object.getBoolean("foo")); 220 assertEquals(false, object.getBoolean("bar")); 221 assertEquals(true, object.getBoolean("baz")); 222 assertEquals(false, object.getBoolean("quux")); 223 assertFalse(object.isNull("foo")); 224 assertFalse(object.isNull("quux")); 225 assertTrue(object.has("foo")); 226 assertTrue(object.has("quux")); 227 assertFalse(object.has("missing")); 228 assertEquals(true, object.optBoolean("foo")); 229 assertEquals(false, object.optBoolean("bar")); 230 assertEquals(true, object.optBoolean("baz")); 231 assertEquals(false, object.optBoolean("quux")); 232 assertEquals(false, object.optBoolean("missing")); 233 assertEquals(true, object.optBoolean("foo", true)); 234 assertEquals(false, object.optBoolean("bar", true)); 235 assertEquals(true, object.optBoolean("baz", true)); 236 assertEquals(false, object.optBoolean("quux", true)); 237 assertEquals(true, object.optBoolean("missing", true)); 238 239 object.put("foo", "truE"); 240 object.put("bar", "FALSE"); 241 assertEquals(true, object.getBoolean("foo")); 242 assertEquals(false, object.getBoolean("bar")); 243 assertEquals(true, object.optBoolean("foo")); 244 assertEquals(false, object.optBoolean("bar")); 245 assertEquals(true, object.optBoolean("foo", false)); 246 assertEquals(false, object.optBoolean("bar", false)); 247 } 248 249 // http://code.google.com/p/android/issues/detail?id=16411 250 public void testCoerceStringToBoolean() throws JSONException { 251 JSONObject object = new JSONObject(); 252 object.put("foo", "maybe"); 253 try { 254 object.getBoolean("foo"); 255 fail(); 256 } catch (JSONException expected) { 257 } 258 assertEquals(false, object.optBoolean("foo")); 259 assertEquals(true, object.optBoolean("foo", true)); 260 } 261 262 public void testNumbers() throws JSONException { 263 JSONObject object = new JSONObject(); 264 object.put("foo", Double.MIN_VALUE); 265 object.put("bar", 9223372036854775806L); 266 object.put("baz", Double.MAX_VALUE); 267 object.put("quux", -0d); 268 assertEquals(4, object.length()); 269 270 String toString = object.toString(); 271 assertTrue(toString, toString.contains("\"foo\":4.9E-324")); 272 assertTrue(toString, toString.contains("\"bar\":9223372036854775806")); 273 assertTrue(toString, toString.contains("\"baz\":1.7976931348623157E308")); 274 275 // toString() and getString() return different values for -0d! 276 assertTrue(toString, toString.contains("\"quux\":-0}") // no trailing decimal point 277 || toString.contains("\"quux\":-0,")); 278 279 assertEquals(Double.MIN_VALUE, object.get("foo")); 280 assertEquals(9223372036854775806L, object.get("bar")); 281 assertEquals(Double.MAX_VALUE, object.get("baz")); 282 assertEquals(-0d, object.get("quux")); 283 assertEquals(Double.MIN_VALUE, object.getDouble("foo")); 284 assertEquals(9.223372036854776E18, object.getDouble("bar")); 285 assertEquals(Double.MAX_VALUE, object.getDouble("baz")); 286 assertEquals(-0d, object.getDouble("quux")); 287 assertEquals(0, object.getLong("foo")); 288 assertEquals(9223372036854775806L, object.getLong("bar")); 289 assertEquals(Long.MAX_VALUE, object.getLong("baz")); 290 assertEquals(0, object.getLong("quux")); 291 assertEquals(0, object.getInt("foo")); 292 assertEquals(-2, object.getInt("bar")); 293 assertEquals(Integer.MAX_VALUE, object.getInt("baz")); 294 assertEquals(0, object.getInt("quux")); 295 assertEquals(Double.MIN_VALUE, object.opt("foo")); 296 assertEquals(9223372036854775806L, object.optLong("bar")); 297 assertEquals(Double.MAX_VALUE, object.optDouble("baz")); 298 assertEquals(0, object.optInt("quux")); 299 assertEquals(Double.MIN_VALUE, object.opt("foo")); 300 assertEquals(9223372036854775806L, object.optLong("bar")); 301 assertEquals(Double.MAX_VALUE, object.optDouble("baz")); 302 assertEquals(0, object.optInt("quux")); 303 assertEquals(Double.MIN_VALUE, object.optDouble("foo", 5.0d)); 304 assertEquals(9223372036854775806L, object.optLong("bar", 1L)); 305 assertEquals(Long.MAX_VALUE, object.optLong("baz", 1L)); 306 assertEquals(0, object.optInt("quux", -1)); 307 assertEquals("4.9E-324", object.getString("foo")); 308 assertEquals("9223372036854775806", object.getString("bar")); 309 assertEquals("1.7976931348623157E308", object.getString("baz")); 310 assertEquals("-0.0", object.getString("quux")); 311 } 312 313 public void testFloats() throws JSONException { 314 JSONObject object = new JSONObject(); 315 try { 316 object.put("foo", (Float) Float.NaN); 317 fail(); 318 } catch (JSONException e) { 319 } 320 try { 321 object.put("foo", (Float) Float.NEGATIVE_INFINITY); 322 fail(); 323 } catch (JSONException e) { 324 } 325 try { 326 object.put("foo", (Float) Float.POSITIVE_INFINITY); 327 fail(); 328 } catch (JSONException e) { 329 } 330 } 331 332 public void testOtherNumbers() throws JSONException { 333 Number nan = new Number() { 334 public int intValue() { 335 throw new UnsupportedOperationException(); 336 } 337 public long longValue() { 338 throw new UnsupportedOperationException(); 339 } 340 public float floatValue() { 341 throw new UnsupportedOperationException(); 342 } 343 public double doubleValue() { 344 return Double.NaN; 345 } 346 @Override public String toString() { 347 return "x"; 348 } 349 }; 350 351 JSONObject object = new JSONObject(); 352 try { 353 object.put("foo", nan); 354 fail("Object.put() accepted a NaN (via a custom Number class)"); 355 } catch (JSONException e) { 356 } 357 } 358 359 public void testForeignObjects() throws JSONException { 360 Object foreign = new Object() { 361 @Override public String toString() { 362 return "x"; 363 } 364 }; 365 366 // foreign object types are accepted and treated as Strings! 367 JSONObject object = new JSONObject(); 368 object.put("foo", foreign); 369 assertEquals("{\"foo\":\"x\"}", object.toString()); 370 } 371 372 public void testNullKeys() { 373 try { 374 new JSONObject().put(null, false); 375 fail(); 376 } catch (JSONException e) { 377 } 378 try { 379 new JSONObject().put(null, 0.0d); 380 fail(); 381 } catch (JSONException e) { 382 } 383 try { 384 new JSONObject().put(null, 5); 385 fail(); 386 } catch (JSONException e) { 387 } 388 try { 389 new JSONObject().put(null, 5L); 390 fail(); 391 } catch (JSONException e) { 392 } 393 try { 394 new JSONObject().put(null, "foo"); 395 fail(); 396 } catch (JSONException e) { 397 } 398 } 399 400 public void testStrings() throws JSONException { 401 JSONObject object = new JSONObject(); 402 object.put("foo", "true"); 403 object.put("bar", "5.5"); 404 object.put("baz", "9223372036854775806"); 405 object.put("quux", "null"); 406 object.put("height", "5\"8' tall"); 407 408 assertTrue(object.toString().contains("\"foo\":\"true\"")); 409 assertTrue(object.toString().contains("\"bar\":\"5.5\"")); 410 assertTrue(object.toString().contains("\"baz\":\"9223372036854775806\"")); 411 assertTrue(object.toString().contains("\"quux\":\"null\"")); 412 assertTrue(object.toString().contains("\"height\":\"5\\\"8' tall\"")); 413 414 assertEquals("true", object.get("foo")); 415 assertEquals("null", object.getString("quux")); 416 assertEquals("5\"8' tall", object.getString("height")); 417 assertEquals("true", object.opt("foo")); 418 assertEquals("5.5", object.optString("bar")); 419 assertEquals("true", object.optString("foo", "x")); 420 assertFalse(object.isNull("foo")); 421 422 assertEquals(true, object.getBoolean("foo")); 423 assertEquals(true, object.optBoolean("foo")); 424 assertEquals(true, object.optBoolean("foo", false)); 425 assertEquals(0, object.optInt("foo")); 426 assertEquals(-2, object.optInt("foo", -2)); 427 428 assertEquals(5.5d, object.getDouble("bar")); 429 assertEquals(5L, object.getLong("bar")); 430 assertEquals(5, object.getInt("bar")); 431 assertEquals(5, object.optInt("bar", 3)); 432 433 // The last digit of the string is a 6 but getLong returns a 7. It's probably parsing as a 434 // double and then converting that to a long. This is consistent with JavaScript. 435 assertEquals(9223372036854775807L, object.getLong("baz")); 436 assertEquals(9.223372036854776E18, object.getDouble("baz")); 437 assertEquals(Integer.MAX_VALUE, object.getInt("baz")); 438 439 assertFalse(object.isNull("quux")); 440 try { 441 object.getDouble("quux"); 442 fail(); 443 } catch (JSONException e) { 444 } 445 assertEquals(Double.NaN, object.optDouble("quux")); 446 assertEquals(-1.0d, object.optDouble("quux", -1.0d)); 447 448 object.put("foo", "TRUE"); 449 assertEquals(true, object.getBoolean("foo")); 450 } 451 452 public void testJSONObjects() throws JSONException { 453 JSONObject object = new JSONObject(); 454 455 JSONArray a = new JSONArray(); 456 JSONObject b = new JSONObject(); 457 object.put("foo", a); 458 object.put("bar", b); 459 460 assertSame(a, object.getJSONArray("foo")); 461 assertSame(b, object.getJSONObject("bar")); 462 try { 463 object.getJSONObject("foo"); 464 fail(); 465 } catch (JSONException e) { 466 } 467 try { 468 object.getJSONArray("bar"); 469 fail(); 470 } catch (JSONException e) { 471 } 472 assertEquals(a, object.optJSONArray("foo")); 473 assertEquals(b, object.optJSONObject("bar")); 474 assertEquals(null, object.optJSONArray("bar")); 475 assertEquals(null, object.optJSONObject("foo")); 476 } 477 478 public void testNullCoercionToString() throws JSONException { 479 JSONObject object = new JSONObject(); 480 object.put("foo", JSONObject.NULL); 481 assertEquals("null", object.getString("foo")); 482 } 483 484 public void testArrayCoercion() throws JSONException { 485 JSONObject object = new JSONObject(); 486 object.put("foo", "[true]"); 487 try { 488 object.getJSONArray("foo"); 489 fail(); 490 } catch (JSONException e) { 491 } 492 } 493 494 public void testObjectCoercion() throws JSONException { 495 JSONObject object = new JSONObject(); 496 object.put("foo", "{}"); 497 try { 498 object.getJSONObject("foo"); 499 fail(); 500 } catch (JSONException e) { 501 } 502 } 503 504 public void testAccumulateValueChecking() throws JSONException { 505 JSONObject object = new JSONObject(); 506 try { 507 object.accumulate("foo", Double.NaN); 508 fail(); 509 } catch (JSONException e) { 510 } 511 object.accumulate("foo", 1); 512 try { 513 object.accumulate("foo", Double.NaN); 514 fail(); 515 } catch (JSONException e) { 516 } 517 object.accumulate("foo", 2); 518 try { 519 object.accumulate("foo", Double.NaN); 520 fail(); 521 } catch (JSONException e) { 522 } 523 } 524 525 public void testToJSONArray() throws JSONException { 526 JSONObject object = new JSONObject(); 527 Object value = new Object(); 528 object.put("foo", true); 529 object.put("bar", 5.0d); 530 object.put("baz", -0.0d); 531 object.put("quux", value); 532 533 JSONArray names = new JSONArray(); 534 names.put("baz"); 535 names.put("quux"); 536 names.put("foo"); 537 538 JSONArray array = object.toJSONArray(names); 539 assertEquals(-0.0d, array.get(0)); 540 assertEquals(value, array.get(1)); 541 assertEquals(true, array.get(2)); 542 543 object.put("foo", false); 544 assertEquals(true, array.get(2)); 545 } 546 547 public void testToJSONArrayMissingNames() throws JSONException { 548 JSONObject object = new JSONObject(); 549 object.put("foo", true); 550 object.put("bar", 5.0d); 551 object.put("baz", JSONObject.NULL); 552 553 JSONArray names = new JSONArray(); 554 names.put("bar"); 555 names.put("foo"); 556 names.put("quux"); 557 names.put("baz"); 558 559 JSONArray array = object.toJSONArray(names); 560 assertEquals(4, array.length()); 561 562 assertEquals(5.0d, array.get(0)); 563 assertEquals(true, array.get(1)); 564 try { 565 array.get(2); 566 fail(); 567 } catch (JSONException e) { 568 } 569 assertEquals(JSONObject.NULL, array.get(3)); 570 } 571 572 public void testToJSONArrayNull() throws JSONException { 573 JSONObject object = new JSONObject(); 574 assertEquals(null, object.toJSONArray(null)); 575 object.put("foo", 5); 576 try { 577 object.toJSONArray(null); 578 } catch (JSONException e) { 579 } 580 } 581 582 public void testToJSONArrayEndsUpEmpty() throws JSONException { 583 JSONObject object = new JSONObject(); 584 object.put("foo", 5); 585 JSONArray array = new JSONArray(); 586 array.put("bar"); 587 assertEquals(1, object.toJSONArray(array).length()); 588 } 589 590 public void testToJSONArrayNonString() throws JSONException { 591 JSONObject object = new JSONObject(); 592 object.put("foo", 5); 593 object.put("null", 10); 594 object.put("false", 15); 595 596 JSONArray names = new JSONArray(); 597 names.put(JSONObject.NULL); 598 names.put(false); 599 names.put("foo"); 600 601 // array elements are converted to strings to do name lookups on the map! 602 JSONArray array = object.toJSONArray(names); 603 assertEquals(3, array.length()); 604 assertEquals(10, array.get(0)); 605 assertEquals(15, array.get(1)); 606 assertEquals(5, array.get(2)); 607 } 608 609 public void testPutUnsupportedNumbers() throws JSONException { 610 JSONObject object = new JSONObject(); 611 try { 612 object.put("foo", Double.NaN); 613 fail(); 614 } catch (JSONException e) { 615 } 616 try { 617 object.put("foo", Double.NEGATIVE_INFINITY); 618 fail(); 619 } catch (JSONException e) { 620 } 621 try { 622 object.put("foo", Double.POSITIVE_INFINITY); 623 fail(); 624 } catch (JSONException e) { 625 } 626 } 627 628 public void testPutUnsupportedNumbersAsObjects() throws JSONException { 629 JSONObject object = new JSONObject(); 630 try { 631 object.put("foo", (Double) Double.NaN); 632 fail(); 633 } catch (JSONException e) { 634 } 635 try { 636 object.put("foo", (Double) Double.NEGATIVE_INFINITY); 637 fail(); 638 } catch (JSONException e) { 639 } 640 try { 641 object.put("foo", (Double) Double.POSITIVE_INFINITY); 642 fail(); 643 } catch (JSONException e) { 644 } 645 } 646 647 /** 648 * Although JSONObject is usually defensive about which numbers it accepts, 649 * it doesn't check inputs in its constructor. 650 */ 651 public void testCreateWithUnsupportedNumbers() throws JSONException { 652 Map<String, Object> contents = new HashMap<String, Object>(); 653 contents.put("foo", Double.NaN); 654 contents.put("bar", Double.NEGATIVE_INFINITY); 655 contents.put("baz", Double.POSITIVE_INFINITY); 656 657 JSONObject object = new JSONObject(contents); 658 assertEquals(Double.NaN, object.get("foo")); 659 assertEquals(Double.NEGATIVE_INFINITY, object.get("bar")); 660 assertEquals(Double.POSITIVE_INFINITY, object.get("baz")); 661 } 662 663 public void testToStringWithUnsupportedNumbers() { 664 // when the object contains an unsupported number, toString returns null! 665 JSONObject object = new JSONObject(Collections.singletonMap("foo", Double.NaN)); 666 assertEquals(null, object.toString()); 667 } 668 669 public void testMapConstructorCopiesContents() throws JSONException { 670 Map<String, Object> contents = new HashMap<String, Object>(); 671 contents.put("foo", 5); 672 JSONObject object = new JSONObject(contents); 673 contents.put("foo", 10); 674 assertEquals(5, object.get("foo")); 675 } 676 677 public void testMapConstructorWithBogusEntries() { 678 Map<Object, Object> contents = new HashMap<Object, Object>(); 679 contents.put(5, 5); 680 681 try { 682 new JSONObject(contents); 683 fail("JSONObject constructor doesn't validate its input!"); 684 } catch (Exception e) { 685 } 686 } 687 688 public void testTokenerConstructor() throws JSONException { 689 JSONObject object = new JSONObject(new JSONTokener("{\"foo\": false}")); 690 assertEquals(1, object.length()); 691 assertEquals(false, object.get("foo")); 692 } 693 694 public void testTokenerConstructorWrongType() throws JSONException { 695 try { 696 new JSONObject(new JSONTokener("[\"foo\", false]")); 697 fail(); 698 } catch (JSONException e) { 699 } 700 } 701 702 public void testTokenerConstructorNull() throws JSONException { 703 try { 704 new JSONObject((JSONTokener) null); 705 fail(); 706 } catch (NullPointerException e) { 707 } 708 } 709 710 public void testTokenerConstructorParseFail() { 711 try { 712 new JSONObject(new JSONTokener("{")); 713 fail(); 714 } catch (JSONException e) { 715 } 716 } 717 718 public void testStringConstructor() throws JSONException { 719 JSONObject object = new JSONObject("{\"foo\": false}"); 720 assertEquals(1, object.length()); 721 assertEquals(false, object.get("foo")); 722 } 723 724 public void testStringConstructorWrongType() throws JSONException { 725 try { 726 new JSONObject("[\"foo\", false]"); 727 fail(); 728 } catch (JSONException e) { 729 } 730 } 731 732 public void testStringConstructorNull() throws JSONException { 733 try { 734 new JSONObject((String) null); 735 fail(); 736 } catch (NullPointerException e) { 737 } 738 } 739 740 public void testStringConstructorParseFail() { 741 try { 742 new JSONObject("{"); 743 fail(); 744 } catch (JSONException e) { 745 } 746 } 747 748 public void testCopyConstructor() throws JSONException { 749 JSONObject source = new JSONObject(); 750 source.put("a", JSONObject.NULL); 751 source.put("b", false); 752 source.put("c", 5); 753 754 JSONObject copy = new JSONObject(source, new String[] { "a", "c" }); 755 assertEquals(2, copy.length()); 756 assertEquals(JSONObject.NULL, copy.get("a")); 757 assertEquals(5, copy.get("c")); 758 assertEquals(null, copy.opt("b")); 759 } 760 761 public void testCopyConstructorMissingName() throws JSONException { 762 JSONObject source = new JSONObject(); 763 source.put("a", JSONObject.NULL); 764 source.put("b", false); 765 source.put("c", 5); 766 767 JSONObject copy = new JSONObject(source, new String[]{ "a", "c", "d" }); 768 assertEquals(2, copy.length()); 769 assertEquals(JSONObject.NULL, copy.get("a")); 770 assertEquals(5, copy.get("c")); 771 assertEquals(0, copy.optInt("b")); 772 } 773 774 public void testAccumulateMutatesInPlace() throws JSONException { 775 JSONObject object = new JSONObject(); 776 object.put("foo", 5); 777 object.accumulate("foo", 6); 778 JSONArray array = object.getJSONArray("foo"); 779 assertEquals("[5,6]", array.toString()); 780 object.accumulate("foo", 7); 781 assertEquals("[5,6,7]", array.toString()); 782 } 783 784 public void testAccumulateExistingArray() throws JSONException { 785 JSONArray array = new JSONArray(); 786 JSONObject object = new JSONObject(); 787 object.put("foo", array); 788 object.accumulate("foo", 5); 789 assertEquals("[5]", array.toString()); 790 } 791 792 public void testAccumulatePutArray() throws JSONException { 793 JSONObject object = new JSONObject(); 794 object.accumulate("foo", 5); 795 assertEquals("{\"foo\":5}", object.toString()); 796 object.accumulate("foo", new JSONArray()); 797 assertEquals("{\"foo\":[5,[]]}", object.toString()); 798 } 799 800 public void testAccumulateNull() { 801 JSONObject object = new JSONObject(); 802 try { 803 object.accumulate(null, 5); 804 fail(); 805 } catch (JSONException e) { 806 } 807 } 808 809 public void testEmptyStringKey() throws JSONException { 810 JSONObject object = new JSONObject(); 811 object.put("", 5); 812 assertEquals(5, object.get("")); 813 assertEquals("{\"\":5}", object.toString()); 814 } 815 816 public void testNullValue() throws JSONException { 817 JSONObject object = new JSONObject(); 818 object.put("foo", JSONObject.NULL); 819 object.put("bar", (Collection) null); 820 821 // there are two ways to represent null; each behaves differently! 822 assertTrue(object.has("foo")); 823 assertFalse(object.has("bar")); 824 assertTrue(object.isNull("foo")); 825 assertTrue(object.isNull("bar")); 826 } 827 828 public void testHas() throws JSONException { 829 JSONObject object = new JSONObject(); 830 object.put("foo", 5); 831 assertTrue(object.has("foo")); 832 assertFalse(object.has("bar")); 833 assertFalse(object.has(null)); 834 } 835 836 public void testOptNull() throws JSONException { 837 JSONObject object = new JSONObject(); 838 object.put("foo", "bar"); 839 assertEquals(null, object.opt(null)); 840 assertEquals(false, object.optBoolean(null)); 841 assertEquals(Double.NaN, object.optDouble(null)); 842 assertEquals(0, object.optInt(null)); 843 assertEquals(0L, object.optLong(null)); 844 assertEquals(null, object.optJSONArray(null)); 845 assertEquals(null, object.optJSONObject(null)); 846 assertEquals("", object.optString(null)); 847 assertEquals(true, object.optBoolean(null, true)); 848 assertEquals(0.0d, object.optDouble(null, 0.0d)); 849 assertEquals(1, object.optInt(null, 1)); 850 assertEquals(1L, object.optLong(null, 1L)); 851 assertEquals("baz", object.optString(null, "baz")); 852 } 853 854 public void testToStringWithIndentFactor() throws JSONException { 855 JSONObject object = new JSONObject(); 856 object.put("foo", new JSONArray(Arrays.asList(5, 6))); 857 object.put("bar", new JSONObject()); 858 String foobar = "{\n" + 859 " \"foo\": [\n" + 860 " 5,\n" + 861 " 6\n" + 862 " ],\n" + 863 " \"bar\": {}\n" + 864 "}"; 865 String barfoo = "{\n" + 866 " \"bar\": {},\n" + 867 " \"foo\": [\n" + 868 " 5,\n" + 869 " 6\n" + 870 " ]\n" + 871 "}"; 872 String string = object.toString(5); 873 assertTrue(string, foobar.equals(string) || barfoo.equals(string)); 874 } 875 876 public void testNames() throws JSONException { 877 JSONObject object = new JSONObject(); 878 object.put("foo", 5); 879 object.put("bar", 6); 880 object.put("baz", 7); 881 JSONArray array = object.names(); 882 assertTrue(array.toString().contains("foo")); 883 assertTrue(array.toString().contains("bar")); 884 assertTrue(array.toString().contains("baz")); 885 } 886 887 public void testKeysEmptyObject() { 888 JSONObject object = new JSONObject(); 889 assertFalse(object.keys().hasNext()); 890 try { 891 object.keys().next(); 892 fail(); 893 } catch (NoSuchElementException e) { 894 } 895 } 896 897 public void testKeys() throws JSONException { 898 JSONObject object = new JSONObject(); 899 object.put("foo", 5); 900 object.put("bar", 6); 901 object.put("foo", 7); 902 903 @SuppressWarnings("unchecked") 904 Iterator<String> keys = (Iterator<String>) object.keys(); 905 Set<String> result = new HashSet<String>(); 906 assertTrue(keys.hasNext()); 907 result.add(keys.next()); 908 assertTrue(keys.hasNext()); 909 result.add(keys.next()); 910 assertFalse(keys.hasNext()); 911 assertEquals(new HashSet<String>(Arrays.asList("foo", "bar")), result); 912 913 try { 914 keys.next(); 915 fail(); 916 } catch (NoSuchElementException e) { 917 } 918 } 919 920 public void testMutatingKeysMutatesObject() throws JSONException { 921 JSONObject object = new JSONObject(); 922 object.put("foo", 5); 923 Iterator keys = object.keys(); 924 keys.next(); 925 keys.remove(); 926 assertEquals(0, object.length()); 927 } 928 929 public void testQuote() { 930 // covered by JSONStringerTest.testEscaping 931 } 932 933 public void testQuoteNull() throws JSONException { 934 assertEquals("\"\"", JSONObject.quote(null)); 935 } 936 937 public void testNumberToString() throws JSONException { 938 assertEquals("5", JSONObject.numberToString(5)); 939 assertEquals("-0", JSONObject.numberToString(-0.0d)); 940 assertEquals("9223372036854775806", JSONObject.numberToString(9223372036854775806L)); 941 assertEquals("4.9E-324", JSONObject.numberToString(Double.MIN_VALUE)); 942 assertEquals("1.7976931348623157E308", JSONObject.numberToString(Double.MAX_VALUE)); 943 try { 944 JSONObject.numberToString(Double.NaN); 945 fail(); 946 } catch (JSONException e) { 947 } 948 try { 949 JSONObject.numberToString(Double.NEGATIVE_INFINITY); 950 fail(); 951 } catch (JSONException e) { 952 } 953 try { 954 JSONObject.numberToString(Double.POSITIVE_INFINITY); 955 fail(); 956 } catch (JSONException e) { 957 } 958 assertEquals("0.001", JSONObject.numberToString(new BigDecimal("0.001"))); 959 assertEquals("9223372036854775806", 960 JSONObject.numberToString(new BigInteger("9223372036854775806"))); 961 try { 962 JSONObject.numberToString(null); 963 fail(); 964 } catch (JSONException e) { 965 } 966 } 967 968 public void test_wrap() throws Exception { 969 assertEquals(JSONObject.NULL, JSONObject.wrap(null)); 970 971 JSONArray a = new JSONArray(); 972 assertEquals(a, JSONObject.wrap(a)); 973 974 JSONObject o = new JSONObject(); 975 assertEquals(o, JSONObject.wrap(o)); 976 977 assertEquals(JSONObject.NULL, JSONObject.wrap(JSONObject.NULL)); 978 979 assertTrue(JSONObject.wrap(new byte[0]) instanceof JSONArray); 980 assertTrue(JSONObject.wrap(new ArrayList<String>()) instanceof JSONArray); 981 assertTrue(JSONObject.wrap(new HashMap<String, String>()) instanceof JSONObject); 982 assertTrue(JSONObject.wrap(Double.valueOf(0)) instanceof Double); 983 assertTrue(JSONObject.wrap("hello") instanceof String); 984 } 985 986 // https://code.google.com/p/android/issues/detail?id=55114 987 public void test_toString_listAsMapValue() throws Exception { 988 ArrayList<Object> list = new ArrayList<Object>(); 989 list.add("a"); 990 list.add(new ArrayList<String>()); 991 Map<String, Object> map = new TreeMap<String, Object>(); 992 map.put("x", "l"); 993 map.put("y", list); 994 assertEquals("{\"x\":\"l\",\"y\":[\"a\",[]]}", new JSONObject(map).toString()); 995 } 996 997 public void testAppendExistingInvalidKey() throws JSONException { 998 JSONObject object = new JSONObject(); 999 object.put("foo", 5); 1000 try { 1001 object.append("foo", 6); 1002 fail(); 1003 } catch (JSONException expected) { 1004 } 1005 } 1006 1007 public void testAppendExistingArray() throws JSONException { 1008 JSONArray array = new JSONArray(); 1009 JSONObject object = new JSONObject(); 1010 object.put("foo", array); 1011 object.append("foo", 5); 1012 assertEquals("[5]", array.toString()); 1013 } 1014 1015 public void testAppendPutArray() throws JSONException { 1016 JSONObject object = new JSONObject(); 1017 object.append("foo", 5); 1018 assertEquals("{\"foo\":[5]}", object.toString()); 1019 object.append("foo", new JSONArray()); 1020 assertEquals("{\"foo\":[5,[]]}", object.toString()); 1021 } 1022 1023 public void testAppendNull() { 1024 JSONObject object = new JSONObject(); 1025 try { 1026 object.append(null, 5); 1027 fail(); 1028 } catch (JSONException e) { 1029 } 1030 } 1031 1032 // https://code.google.com/p/android/issues/detail?id=103641 1033 public void testInvalidUnicodeEscape() { 1034 try { 1035 new JSONObject("{\"q\":\"\\u\", \"r\":[]}"); 1036 fail(); 1037 } catch (JSONException expected) { 1038 } 1039 } 1040} 1041