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