1 package com.fasterxml.jackson.databind.node; 2 3 import java.io.IOException; 4 import java.math.BigInteger; 5 import java.util.*; 6 7 import static org.junit.Assert.*; 8 9 import com.fasterxml.jackson.annotation.*; 10 11 import com.fasterxml.jackson.core.*; 12 import com.fasterxml.jackson.core.JsonParser.NumberType; 13 import com.fasterxml.jackson.core.exc.InputCoercionException; 14 import com.fasterxml.jackson.databind.*; 15 import com.fasterxml.jackson.databind.exc.InvalidFormatException; 16 17 public class TestTreeTraversingParser 18 extends BaseMapTest 19 { 20 static class Person { 21 public String name; 22 public int magicNumber; 23 public List<String> kids; 24 } 25 26 @JsonIgnoreProperties(ignoreUnknown=true) 27 public static class Jackson370Bean { 28 public Inner inner; 29 } 30 31 public static class Inner { 32 public String value; 33 } 34 35 /* 36 /********************************************************** 37 /* Test methods 38 /********************************************************** 39 */ 40 41 private final ObjectMapper MAPPER = newJsonMapper(); 42 testSimple()43 public void testSimple() throws Exception 44 { 45 // For convenience, parse tree from JSON first 46 final String JSON = 47 "{ \"a\" : 123, \"list\" : [ 12.25, null, true, { }, [ ] ] }"; 48 JsonNode tree = MAPPER.readTree(JSON); 49 JsonParser p = tree.traverse(); 50 51 assertNull(p.currentToken()); 52 assertNull(p.currentName()); 53 54 assertToken(JsonToken.START_OBJECT, p.nextToken()); 55 assertNull(p.currentName()); 56 assertEquals("Expected START_OBJECT", JsonToken.START_OBJECT.asString(), p.getText()); 57 58 assertToken(JsonToken.FIELD_NAME, p.nextToken()); 59 assertEquals("a", p.currentName()); 60 assertEquals("a", p.getText()); 61 62 assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); 63 assertEquals("a", p.currentName()); 64 assertEquals(123, p.getIntValue()); 65 assertEquals("123", p.getText()); 66 67 assertToken(JsonToken.FIELD_NAME, p.nextToken()); 68 assertEquals("list", p.currentName()); 69 assertEquals("list", p.getText()); 70 71 assertToken(JsonToken.START_ARRAY, p.nextToken()); 72 assertEquals("list", p.currentName()); 73 assertEquals(JsonToken.START_ARRAY.asString(), p.getText()); 74 75 assertToken(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken()); 76 assertNull(p.currentName()); 77 assertEquals(12.25, p.getDoubleValue(), 0); 78 assertEquals("12.25", p.getText()); 79 80 assertToken(JsonToken.VALUE_NULL, p.nextToken()); 81 assertNull(p.currentName()); 82 assertEquals(JsonToken.VALUE_NULL.asString(), p.getText()); 83 84 assertToken(JsonToken.VALUE_TRUE, p.nextToken()); 85 assertNull(p.currentName()); 86 assertTrue(p.getBooleanValue()); 87 assertEquals(JsonToken.VALUE_TRUE.asString(), p.getText()); 88 89 assertToken(JsonToken.START_OBJECT, p.nextToken()); 90 assertNull(p.currentName()); 91 assertToken(JsonToken.END_OBJECT, p.nextToken()); 92 assertNull(p.currentName()); 93 94 assertToken(JsonToken.START_ARRAY, p.nextToken()); 95 assertNull(p.currentName()); 96 assertToken(JsonToken.END_ARRAY, p.nextToken()); 97 assertNull(p.currentName()); 98 99 assertToken(JsonToken.END_ARRAY, p.nextToken()); 100 101 assertToken(JsonToken.END_OBJECT, p.nextToken()); 102 assertNull(p.currentName()); 103 104 assertNull(p.nextToken()); 105 106 p.close(); 107 assertTrue(p.isClosed()); 108 } 109 testArray()110 public void testArray() throws Exception 111 { 112 // For convenience, parse tree from JSON first 113 JsonParser p = MAPPER.readTree("[]").traverse(); 114 assertToken(JsonToken.START_ARRAY, p.nextToken()); 115 assertToken(JsonToken.END_ARRAY, p.nextToken()); 116 p.close(); 117 118 p = MAPPER.readTree("[[]]").traverse(); 119 assertToken(JsonToken.START_ARRAY, p.nextToken()); 120 assertToken(JsonToken.START_ARRAY, p.nextToken()); 121 assertToken(JsonToken.END_ARRAY, p.nextToken()); 122 assertToken(JsonToken.END_ARRAY, p.nextToken()); 123 p.close(); 124 125 p = MAPPER.readTree("[[ 12.1 ]]").traverse(); 126 assertToken(JsonToken.START_ARRAY, p.nextToken()); 127 assertToken(JsonToken.START_ARRAY, p.nextToken()); 128 assertToken(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken()); 129 assertToken(JsonToken.END_ARRAY, p.nextToken()); 130 assertToken(JsonToken.END_ARRAY, p.nextToken()); 131 p.close(); 132 } 133 testNested()134 public void testNested() throws Exception 135 { 136 // For convenience, parse tree from JSON first 137 final String JSON = 138 "{\"coordinates\":[[[-3,\n1],[179.859681,51.175092]]]}" 139 ; 140 JsonNode tree = MAPPER.readTree(JSON); 141 JsonParser p = tree.traverse(); 142 assertToken(JsonToken.START_OBJECT, p.nextToken()); 143 assertToken(JsonToken.FIELD_NAME, p.nextToken()); 144 145 assertToken(JsonToken.START_ARRAY, p.nextToken()); 146 assertToken(JsonToken.START_ARRAY, p.nextToken()); 147 148 assertToken(JsonToken.START_ARRAY, p.nextToken()); 149 assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); 150 assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); 151 assertToken(JsonToken.END_ARRAY, p.nextToken()); 152 153 assertToken(JsonToken.START_ARRAY, p.nextToken()); 154 assertToken(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken()); 155 assertToken(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken()); 156 assertToken(JsonToken.END_ARRAY, p.nextToken()); 157 158 assertToken(JsonToken.END_ARRAY, p.nextToken()); 159 assertToken(JsonToken.END_ARRAY, p.nextToken()); 160 161 assertToken(JsonToken.END_OBJECT, p.nextToken()); 162 p.close(); 163 } 164 165 /** 166 * Unit test that verifies that we can (re)parse sample document 167 * from JSON specification. 168 */ testSpecDoc()169 public void testSpecDoc() throws Exception 170 { 171 JsonNode tree = MAPPER.readTree(SAMPLE_DOC_JSON_SPEC); 172 JsonParser p = tree.traverse(); 173 verifyJsonSpecSampleDoc(p, true); 174 p.close(); 175 } 176 testBinaryPojo()177 public void testBinaryPojo() throws Exception 178 { 179 byte[] inputBinary = new byte[] { 1, 2, 100 }; 180 POJONode n = new POJONode(inputBinary); 181 JsonParser p = n.traverse(); 182 183 assertNull(p.currentToken()); 184 assertToken(JsonToken.VALUE_EMBEDDED_OBJECT, p.nextToken()); 185 byte[] data = p.getBinaryValue(); 186 assertNotNull(data); 187 assertArrayEquals(inputBinary, data); 188 Object pojo = p.getEmbeddedObject(); 189 assertSame(data, pojo); 190 p.close(); 191 } 192 testBinaryNode()193 public void testBinaryNode() throws Exception 194 { 195 byte[] inputBinary = new byte[] { 0, -5 }; 196 BinaryNode n = new BinaryNode(inputBinary); 197 JsonParser p = n.traverse(); 198 199 assertNull(p.currentToken()); 200 // exposed as POJO... not as VALUE_STRING 201 assertToken(JsonToken.VALUE_EMBEDDED_OBJECT, p.nextToken()); 202 byte[] data = p.getBinaryValue(); 203 assertNotNull(data); 204 assertArrayEquals(inputBinary, data); 205 206 // but as importantly, can be viewed as base64 encoded thing: 207 assertEquals("APs=", p.getText()); 208 209 assertNull(p.nextToken()); 210 p.close(); 211 } 212 testTextAsBinary()213 public void testTextAsBinary() throws Exception 214 { 215 TextNode n = new TextNode(" APs=\n"); 216 JsonParser p = n.traverse(); 217 assertNull(p.currentToken()); 218 assertToken(JsonToken.VALUE_STRING, p.nextToken()); 219 byte[] data = p.getBinaryValue(); 220 assertNotNull(data); 221 assertArrayEquals(new byte[] { 0, -5 }, data); 222 223 assertNull(p.nextToken()); 224 p.close(); 225 assertTrue(p.isClosed()); 226 227 // Also: let's verify we get an exception for garbage... 228 n = new TextNode("?!??"); 229 p = n.traverse(); 230 assertToken(JsonToken.VALUE_STRING, p.nextToken()); 231 try { 232 p.getBinaryValue(); 233 } catch (InvalidFormatException e) { 234 verifyException(e, "Illegal character"); 235 } 236 p.close(); 237 } 238 239 /** 240 * Very simple test case to verify that tree-to-POJO 241 * conversion works ok 242 */ testDataBind()243 public void testDataBind() throws Exception 244 { 245 JsonNode tree = MAPPER.readTree 246 ("{ \"name\" : \"Tatu\", \n" 247 +"\"magicNumber\" : 42," 248 +"\"kids\" : [ \"Leo\", \"Lila\", \"Leia\" ] \n" 249 +"}"); 250 Person tatu = MAPPER.treeToValue(tree, Person.class); 251 assertNotNull(tatu); 252 assertEquals(42, tatu.magicNumber); 253 assertEquals("Tatu", tatu.name); 254 assertNotNull(tatu.kids); 255 assertEquals(3, tatu.kids.size()); 256 assertEquals("Leo", tatu.kids.get(0)); 257 assertEquals("Lila", tatu.kids.get(1)); 258 assertEquals("Leia", tatu.kids.get(2)); 259 } 260 testSkipChildrenWrt370()261 public void testSkipChildrenWrt370() throws Exception 262 { 263 ObjectNode n = MAPPER.createObjectNode(); 264 n.putObject("inner").put("value", "test"); 265 n.putObject("unknown").putNull("inner"); 266 Jackson370Bean obj = MAPPER.readValue(n.traverse(), Jackson370Bean.class); 267 assertNotNull(obj.inner); 268 assertEquals("test", obj.inner.value); 269 } 270 271 // // // Numeric coercion checks, [databind#2189] 272 testNumberOverflowInt()273 public void testNumberOverflowInt() throws IOException 274 { 275 final long tooBig = 1L + Integer.MAX_VALUE; 276 try (final JsonParser p = MAPPER.readTree("[ "+tooBig+" ]").traverse()) { 277 assertToken(JsonToken.START_ARRAY, p.nextToken()); 278 assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); 279 assertEquals(NumberType.LONG, p.getNumberType()); 280 try { 281 p.getIntValue(); 282 fail("Expected failure for `int` overflow"); 283 } catch (InputCoercionException e) { 284 verifyException(e, "Numeric value ("+tooBig+") out of range of int"); 285 } 286 } 287 try (final JsonParser p = MAPPER.readTree("{ \"value\" : "+tooBig+" }").traverse()) { 288 assertToken(JsonToken.START_OBJECT, p.nextToken()); 289 assertToken(JsonToken.FIELD_NAME, p.nextToken()); 290 assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); 291 assertEquals(NumberType.LONG, p.getNumberType()); 292 try { 293 p.getIntValue(); 294 fail("Expected failure for `int` overflow"); 295 } catch (InputCoercionException e) { 296 verifyException(e, "Numeric value ("+tooBig+") out of range of int"); 297 } 298 } 299 // But also from floating-point 300 final String tooBig2 = "1.0e10"; 301 try (final JsonParser p = MAPPER.readTree("[ "+tooBig2+" ]").traverse()) { 302 assertToken(JsonToken.START_ARRAY, p.nextToken()); 303 assertToken(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken()); 304 assertEquals(NumberType.DOUBLE, p.getNumberType()); 305 try { 306 p.getIntValue(); 307 fail("Expected failure for `int` overflow"); 308 } catch (InputCoercionException e) { 309 verifyException(e, "Numeric value ("+tooBig2+") out of range of int"); 310 } 311 } 312 } 313 testNumberOverflowLong()314 public void testNumberOverflowLong() throws IOException 315 { 316 final BigInteger tooBig = BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.ONE); 317 try (final JsonParser p = MAPPER.readTree("[ "+tooBig+" ]").traverse()) { 318 assertToken(JsonToken.START_ARRAY, p.nextToken()); 319 assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); 320 assertEquals(NumberType.BIG_INTEGER, p.getNumberType()); 321 try { 322 p.getLongValue(); 323 fail("Expected failure for `long` overflow"); 324 } catch (InputCoercionException e) { 325 verifyException(e, "Numeric value ("+tooBig+") out of range of long"); 326 } 327 } 328 try (final JsonParser p = MAPPER.readTree("{ \"value\" : "+tooBig+" }").traverse()) { 329 assertToken(JsonToken.START_OBJECT, p.nextToken()); 330 assertToken(JsonToken.FIELD_NAME, p.nextToken()); 331 assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); 332 assertEquals(NumberType.BIG_INTEGER, p.getNumberType()); 333 try { 334 p.getLongValue(); 335 fail("Expected failure for `long` overflow"); 336 } catch (InputCoercionException e) { 337 verifyException(e, "Numeric value ("+tooBig+") out of range of long"); 338 } 339 } 340 // But also from floating-point 341 final String tooBig2 = "1.0e30"; 342 try (final JsonParser p = MAPPER.readTree("[ "+tooBig2+" ]").traverse()) { 343 assertToken(JsonToken.START_ARRAY, p.nextToken()); 344 assertToken(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken()); 345 assertEquals(NumberType.DOUBLE, p.getNumberType()); 346 try { 347 p.getLongValue(); 348 fail("Expected failure for `long` overflow"); 349 } catch (InputCoercionException e) { 350 verifyException(e, "Numeric value ("+tooBig2+") out of range of long"); 351 } 352 } 353 354 // Plus, wrt [databind#2393], NON-failing cases 355 final long[] okValues = new long[] { 1L+Integer.MAX_VALUE, -1L + Integer.MIN_VALUE, 356 Long.MAX_VALUE, Long.MIN_VALUE }; 357 for (long okValue : okValues) { 358 try (final JsonParser p = MAPPER.readTree("{ \"value\" : "+okValue+" }").traverse()) { 359 assertToken(JsonToken.START_OBJECT, p.nextToken()); 360 assertToken(JsonToken.FIELD_NAME, p.nextToken()); 361 assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); 362 assertEquals(NumberType.LONG, p.getNumberType()); 363 assertEquals(okValue, p.getLongValue()); 364 assertToken(JsonToken.END_OBJECT, p.nextToken()); 365 } 366 } 367 } 368 } 369