1 package com.fasterxml.jackson.databind.node; 2 3 import java.util.Comparator; 4 5 import com.fasterxml.jackson.core.*; 6 import com.fasterxml.jackson.core.io.SerializedString; 7 import com.fasterxml.jackson.databind.*; 8 import com.fasterxml.jackson.databind.testutil.NoCheckSubTypeValidator; 9 import com.fasterxml.jackson.databind.util.RawValue; 10 11 /** 12 * Basic tests for {@link JsonNode} base class and some features 13 * of implementation classes 14 */ 15 public class TestJsonNode extends NodeTestBase 16 { 17 private final ObjectMapper MAPPER = objectMapper(); 18 testBoolean()19 public void testBoolean() throws Exception 20 { 21 BooleanNode f = BooleanNode.getFalse(); 22 assertNotNull(f); 23 assertTrue(f.isBoolean()); 24 assertSame(f, BooleanNode.valueOf(false)); 25 assertStandardEquals(f); 26 assertFalse(f.booleanValue()); 27 assertFalse(f.asBoolean()); 28 assertEquals("false", f.asText()); 29 assertEquals(JsonToken.VALUE_FALSE, f.asToken()); 30 31 // and ditto for true 32 BooleanNode t = BooleanNode.getTrue(); 33 assertNotNull(t); 34 assertTrue(t.isBoolean()); 35 assertSame(t, BooleanNode.valueOf(true)); 36 assertStandardEquals(t); 37 assertTrue(t.booleanValue()); 38 assertTrue(t.asBoolean()); 39 assertEquals("true", t.asText()); 40 assertEquals(JsonToken.VALUE_TRUE, t.asToken()); 41 42 assertNodeNumbers(f, 0, 0.0); 43 assertNodeNumbers(t, 1, 1.0); 44 45 JsonNode result = objectMapper().readTree("true\n"); 46 assertFalse(result.isNull()); 47 assertFalse(result.isNumber()); 48 assertFalse(result.isTextual()); 49 assertTrue(result.isBoolean()); 50 assertType(result, BooleanNode.class); 51 assertTrue(result.booleanValue()); 52 assertEquals("true", result.asText()); 53 assertFalse(result.isMissingNode()); 54 55 // also, equality should work ok 56 assertEquals(result, BooleanNode.valueOf(true)); 57 assertEquals(result, BooleanNode.getTrue()); 58 } 59 testBinary()60 public void testBinary() throws Exception 61 { 62 assertNull(BinaryNode.valueOf(null)); 63 assertNull(BinaryNode.valueOf(null, 0, 0)); 64 65 BinaryNode empty = BinaryNode.valueOf(new byte[1], 0, 0); 66 assertSame(BinaryNode.EMPTY_BINARY_NODE, empty); 67 assertStandardEquals(empty); 68 69 byte[] data = new byte[3]; 70 data[1] = (byte) 3; 71 BinaryNode n = BinaryNode.valueOf(data, 1, 1); 72 data[2] = (byte) 3; 73 BinaryNode n2 = BinaryNode.valueOf(data, 2, 1); 74 assertTrue(n.equals(n2)); 75 assertEquals("\"Aw==\"", n.toString()); 76 77 assertEquals("AAMD", new BinaryNode(data).asText()); 78 assertNodeNumbersForNonNumeric(n); 79 } 80 testPOJO()81 public void testPOJO() 82 { 83 POJONode n = new POJONode("x"); // not really a pojo but that's ok 84 assertStandardEquals(n); 85 assertEquals(n, new POJONode("x")); 86 assertEquals("x", n.asText()); 87 // 10-Dec-2018, tatu: With 2.10, should serialize same as via ObjectMapper/ObjectWriter 88 assertEquals("\"x\"", n.toString()); 89 90 assertEquals(new POJONode(null), new POJONode(null)); 91 92 // default; non-numeric 93 assertNodeNumbersForNonNumeric(n); 94 // but if wrapping actual number, use it 95 assertNodeNumbers(new POJONode(Integer.valueOf(123)), 123, 123.0); 96 } 97 98 // [databind#743] testRawValue()99 public void testRawValue() throws Exception 100 { 101 ObjectNode root = MAPPER.createObjectNode(); 102 root.putRawValue("a", new RawValue(new SerializedString("[1, 2, 3]"))); 103 104 assertEquals("{\"a\":[1, 2, 3]}", MAPPER.writeValueAsString(root)); 105 } 106 107 // [databind#790] testCustomComparators()108 public void testCustomComparators() throws Exception 109 { 110 ObjectNode nestedObject1 = MAPPER.createObjectNode(); 111 nestedObject1.put("value", 6); 112 ArrayNode nestedArray1 = MAPPER.createArrayNode(); 113 nestedArray1.add(7); 114 ObjectNode root1 = MAPPER.createObjectNode(); 115 root1.put("value", 5); 116 root1.set("nested_object", nestedObject1); 117 root1.set("nested_array", nestedArray1); 118 119 ObjectNode nestedObject2 = MAPPER.createObjectNode(); 120 nestedObject2.put("value", 6.9); 121 ArrayNode nestedArray2 = MAPPER.createArrayNode(); 122 nestedArray2.add(7.0); 123 ObjectNode root2 = MAPPER.createObjectNode(); 124 root2.put("value", 5.0); 125 root2.set("nested_object", nestedObject2); 126 root2.set("nested_array", nestedArray2); 127 128 // default equals(): not strictly equal 129 assertFalse(root1.equals(root2)); 130 assertFalse(root2.equals(root1)); 131 assertTrue(root1.equals(root1)); 132 assertTrue(root2.equals(root2)); 133 134 assertTrue(nestedArray1.equals(nestedArray1)); 135 assertFalse(nestedArray1.equals(nestedArray2)); 136 assertFalse(nestedArray2.equals(nestedArray1)); 137 138 // but. Custom comparator can make all the difference 139 Comparator<JsonNode> cmp = new Comparator<JsonNode>() { 140 141 @Override 142 public int compare(JsonNode o1, JsonNode o2) { 143 if (o1 instanceof ContainerNode || o2 instanceof ContainerNode) { 144 fail("container nodes should be traversed, comparator should not be invoked"); 145 } 146 if (o1.equals(o2)) { 147 return 0; 148 } 149 if ((o1 instanceof NumericNode) && (o2 instanceof NumericNode)) { 150 int d1 = ((NumericNode) o1).asInt(); 151 int d2 = ((NumericNode) o2).asInt(); 152 if (d1 == d2) { // strictly equals because it's integral value 153 return 0; 154 } 155 if (d1 < d2) { 156 return -1; 157 } 158 return 1; 159 } 160 return 0; 161 } 162 }; 163 assertTrue(root1.equals(cmp, root2)); 164 assertTrue(root2.equals(cmp, root1)); 165 assertTrue(root1.equals(cmp, root1)); 166 assertTrue(root2.equals(cmp, root2)); 167 168 ArrayNode array3 = MAPPER.createArrayNode(); 169 array3.add(123); 170 171 assertFalse(root2.equals(cmp, nestedArray1)); 172 assertTrue(nestedArray1.equals(cmp, nestedArray1)); 173 assertFalse(nestedArray1.equals(cmp, root2)); 174 assertFalse(nestedArray1.equals(cmp, array3)); 175 } 176 177 // [databind#793] testArrayWithDefaultTyping()178 public void testArrayWithDefaultTyping() throws Exception 179 { 180 ObjectMapper mapper = new ObjectMapper() 181 .activateDefaultTyping(NoCheckSubTypeValidator.instance); 182 183 JsonNode array = mapper.readTree("[ 1, 2 ]"); 184 assertTrue(array.isArray()); 185 assertEquals(2, array.size()); 186 187 JsonNode obj = mapper.readTree("{ \"a\" : 2 }"); 188 assertTrue(obj.isObject()); 189 assertEquals(1, obj.size()); 190 assertEquals(2, obj.path("a").asInt()); 191 } 192 } 193