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