1 package com.fasterxml.jackson.databind.deser.std; 2 3 import java.io.IOException; 4 import java.lang.reflect.Array; 5 import java.util.Arrays; 6 7 import com.fasterxml.jackson.annotation.JsonFormat; 8 import com.fasterxml.jackson.annotation.Nulls; 9 import com.fasterxml.jackson.core.*; 10 import com.fasterxml.jackson.databind.*; 11 import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; 12 import com.fasterxml.jackson.databind.deser.ContextualDeserializer; 13 import com.fasterxml.jackson.databind.deser.NullValueProvider; 14 import com.fasterxml.jackson.databind.deser.impl.NullsConstantProvider; 15 import com.fasterxml.jackson.databind.deser.impl.NullsFailProvider; 16 import com.fasterxml.jackson.databind.exc.InvalidNullException; 17 import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; 18 import com.fasterxml.jackson.databind.type.LogicalType; 19 import com.fasterxml.jackson.databind.util.AccessPattern; 20 import com.fasterxml.jackson.databind.util.ArrayBuilders; 21 22 /** 23 * Container for deserializers used for instantiating "primitive arrays", 24 * arrays that contain non-object java primitive types. 25 */ 26 @SuppressWarnings("serial") 27 public abstract class PrimitiveArrayDeserializers<T> extends StdDeserializer<T> 28 implements ContextualDeserializer // since 2.7 29 { 30 /** 31 * Specific override for this instance (from proper, or global per-type overrides) 32 * to indicate whether single value may be taken to mean an unwrapped one-element array 33 * or not. If null, left to global defaults. 34 * 35 * @since 2.7 36 */ 37 protected final Boolean _unwrapSingle; 38 39 // since 2.9 40 private transient Object _emptyValue; 41 42 /** 43 * Flag that indicates need for special handling; either failing 44 * (throw exception) or skipping 45 */ 46 protected final NullValueProvider _nuller; 47 48 /* 49 /******************************************************** 50 /* Life-cycle 51 /******************************************************** 52 */ 53 PrimitiveArrayDeserializers(Class<T> cls)54 protected PrimitiveArrayDeserializers(Class<T> cls) { 55 super(cls); 56 _unwrapSingle = null; 57 _nuller = null; 58 } 59 60 /** 61 * @since 2.7 62 */ PrimitiveArrayDeserializers(PrimitiveArrayDeserializers<?> base, NullValueProvider nuller, Boolean unwrapSingle)63 protected PrimitiveArrayDeserializers(PrimitiveArrayDeserializers<?> base, 64 NullValueProvider nuller, Boolean unwrapSingle) { 65 super(base._valueClass); 66 _unwrapSingle = unwrapSingle; 67 _nuller = nuller; 68 } 69 forType(Class<?> rawType)70 public static JsonDeserializer<?> forType(Class<?> rawType) 71 { 72 // Start with more common types... 73 if (rawType == Integer.TYPE) { 74 return IntDeser.instance; 75 } 76 if (rawType == Long.TYPE) { 77 return LongDeser.instance; 78 } 79 80 if (rawType == Byte.TYPE) { 81 return new ByteDeser(); 82 } 83 if (rawType == Short.TYPE) { 84 return new ShortDeser(); 85 } 86 if (rawType == Float.TYPE) { 87 return new FloatDeser(); 88 } 89 if (rawType == Double.TYPE) { 90 return new DoubleDeser(); 91 } 92 if (rawType == Boolean.TYPE) { 93 return new BooleanDeser(); 94 } 95 if (rawType == Character.TYPE) { 96 return new CharDeser(); 97 } 98 throw new IllegalStateException(); 99 } 100 101 @Override createContextual(DeserializationContext ctxt, BeanProperty property)102 public JsonDeserializer<?> createContextual(DeserializationContext ctxt, 103 BeanProperty property) throws JsonMappingException 104 { 105 Boolean unwrapSingle = findFormatFeature(ctxt, property, _valueClass, 106 JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY); 107 NullValueProvider nuller = null; 108 109 Nulls nullStyle = findContentNullStyle(ctxt, property); 110 if (nullStyle == Nulls.SKIP) { 111 nuller = NullsConstantProvider.skipper(); 112 } else if (nullStyle == Nulls.FAIL) { 113 if (property == null) { 114 // 09-Dec-2019, tatu: [databind#2567] need to ensure correct target type 115 nuller = NullsFailProvider.constructForRootValue(ctxt.constructType(_valueClass.getComponentType())); 116 } else { 117 // 09-Dec-2019, tatu: [databind#2567] need to ensure correct target type 118 nuller = NullsFailProvider.constructForProperty(property, property.getType().getContentType()); 119 } 120 } 121 if ((unwrapSingle == _unwrapSingle) && (nuller == _nuller)) { 122 return this; 123 } 124 return withResolved(nuller, unwrapSingle); 125 } 126 127 /* 128 /******************************************************** 129 /* Abstract methods for sub-classes to implement 130 /******************************************************** 131 */ 132 133 /** 134 * @since 2.9 135 */ _concat(T oldValue, T newValue)136 protected abstract T _concat(T oldValue, T newValue); 137 handleSingleElementUnwrapped(JsonParser p, DeserializationContext ctxt)138 protected abstract T handleSingleElementUnwrapped(JsonParser p, 139 DeserializationContext ctxt) throws IOException; 140 141 /** 142 * @since 2.9 143 */ withResolved(NullValueProvider nuller, Boolean unwrapSingle)144 protected abstract PrimitiveArrayDeserializers<?> withResolved(NullValueProvider nuller, 145 Boolean unwrapSingle); 146 147 // since 2.9 _constructEmpty()148 protected abstract T _constructEmpty(); 149 150 /* 151 /******************************************************** 152 /* Default implementations 153 /******************************************************** 154 */ 155 156 @Override // since 2.12 logicalType()157 public LogicalType logicalType() { 158 return LogicalType.Array; 159 } 160 161 @Override // since 2.9 supportsUpdate(DeserializationConfig config)162 public Boolean supportsUpdate(DeserializationConfig config) { 163 return Boolean.TRUE; 164 } 165 166 @Override getEmptyAccessPattern()167 public AccessPattern getEmptyAccessPattern() { 168 // Empty values shareable freely 169 return AccessPattern.CONSTANT; 170 } 171 172 @Override // since 2.9 getEmptyValue(DeserializationContext ctxt)173 public Object getEmptyValue(DeserializationContext ctxt) throws JsonMappingException { 174 Object empty = _emptyValue; 175 if (empty == null) { 176 _emptyValue = empty = _constructEmpty(); 177 } 178 return empty; 179 } 180 181 @Override deserializeWithType(JsonParser p, DeserializationContext ctxt, TypeDeserializer typeDeserializer)182 public Object deserializeWithType(JsonParser p, DeserializationContext ctxt, 183 TypeDeserializer typeDeserializer) throws IOException 184 { 185 // Should there be separate handling for base64 stuff? 186 // for now this should be enough: 187 return typeDeserializer.deserializeTypedFromArray(p, ctxt); 188 } 189 190 @Override deserialize(JsonParser p, DeserializationContext ctxt, T existing)191 public T deserialize(JsonParser p, DeserializationContext ctxt, T existing) throws IOException 192 { 193 T newValue = deserialize(p, ctxt); 194 if (existing == null) { 195 return newValue; 196 } 197 int len = Array.getLength(existing); 198 if (len == 0) { 199 return newValue; 200 } 201 return _concat(existing, newValue); 202 } 203 204 /* 205 /******************************************************** 206 /* Helper methods for sub-classes 207 /******************************************************** 208 */ 209 210 @SuppressWarnings("unchecked") handleNonArray(JsonParser p, DeserializationContext ctxt)211 protected T handleNonArray(JsonParser p, DeserializationContext ctxt) throws IOException 212 { 213 // Empty String can become null... 214 if (p.hasToken(JsonToken.VALUE_STRING)) { 215 return _deserializeFromString(p, ctxt); 216 } 217 boolean canWrap = (_unwrapSingle == Boolean.TRUE) || 218 ((_unwrapSingle == null) && 219 ctxt.isEnabled(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY)); 220 if (canWrap) { 221 return handleSingleElementUnwrapped(p, ctxt); 222 } 223 return (T) ctxt.handleUnexpectedToken(_valueClass, p); 224 } 225 _failOnNull(DeserializationContext ctxt)226 protected void _failOnNull(DeserializationContext ctxt) throws IOException 227 { 228 throw InvalidNullException.from(ctxt, null, ctxt.constructType(_valueClass)); 229 } 230 231 /* 232 /******************************************************** 233 /* Actual deserializers: efficient String[], char[] deserializers 234 /******************************************************** 235 */ 236 237 @JacksonStdImpl 238 final static class CharDeser 239 extends PrimitiveArrayDeserializers<char[]> 240 { 241 private static final long serialVersionUID = 1L; 242 CharDeser()243 public CharDeser() { super(char[].class); } CharDeser(CharDeser base, NullValueProvider nuller, Boolean unwrapSingle)244 protected CharDeser(CharDeser base, NullValueProvider nuller, Boolean unwrapSingle) { 245 super(base, nuller, unwrapSingle); 246 } 247 248 @Override withResolved(NullValueProvider nuller, Boolean unwrapSingle)249 protected PrimitiveArrayDeserializers<?> withResolved(NullValueProvider nuller, 250 Boolean unwrapSingle) { 251 // 11-Dec-2015, tatu: Not sure how re-wrapping would work; omit 252 return this; 253 } 254 255 @Override _constructEmpty()256 protected char[] _constructEmpty() { 257 return new char[0]; 258 } 259 260 @Override deserialize(JsonParser p, DeserializationContext ctxt)261 public char[] deserialize(JsonParser p, DeserializationContext ctxt) throws IOException 262 { 263 /* Won't take arrays, must get a String (could also 264 * convert other tokens to Strings... but let's not bother 265 * yet, doesn't seem to make sense) 266 */ 267 if (p.hasToken(JsonToken.VALUE_STRING)) { 268 // note: can NOT return shared internal buffer, must copy: 269 char[] buffer = p.getTextCharacters(); 270 int offset = p.getTextOffset(); 271 int len = p.getTextLength(); 272 273 char[] result = new char[len]; 274 System.arraycopy(buffer, offset, result, 0, len); 275 return result; 276 } 277 if (p.isExpectedStartArrayToken()) { 278 // Let's actually build as a String, then get chars 279 StringBuilder sb = new StringBuilder(64); 280 JsonToken t; 281 while ((t = p.nextToken()) != JsonToken.END_ARRAY) { 282 String str; 283 if (t == JsonToken.VALUE_STRING) { 284 str = p.getText(); 285 } else if (t == JsonToken.VALUE_NULL) { 286 if (_nuller != null) { 287 _nuller.getNullValue(ctxt); 288 continue; 289 } 290 _verifyNullForPrimitive(ctxt); 291 str = "\0"; 292 } else { 293 CharSequence cs = (CharSequence) ctxt.handleUnexpectedToken(Character.TYPE, p); 294 str = cs.toString(); 295 } 296 if (str.length() != 1) { 297 ctxt.reportInputMismatch(this, 298 "Cannot convert a JSON String of length %d into a char element of char array", str.length()); 299 } 300 sb.append(str.charAt(0)); 301 } 302 return sb.toString().toCharArray(); 303 } 304 // or, maybe an embedded object? 305 if (p.hasToken(JsonToken.VALUE_EMBEDDED_OBJECT)) { 306 Object ob = p.getEmbeddedObject(); 307 if (ob == null) return null; 308 if (ob instanceof char[]) { 309 return (char[]) ob; 310 } 311 if (ob instanceof String) { 312 return ((String) ob).toCharArray(); 313 } 314 // 04-Feb-2011, tatu: byte[] can be converted; assuming base64 is wanted 315 if (ob instanceof byte[]) { 316 return Base64Variants.getDefaultVariant().encode((byte[]) ob, false).toCharArray(); 317 } 318 // not recognized, just fall through 319 } 320 return (char[]) ctxt.handleUnexpectedToken(_valueClass, p); 321 } 322 323 @Override handleSingleElementUnwrapped(JsonParser p, DeserializationContext ctxt)324 protected char[] handleSingleElementUnwrapped(JsonParser p, 325 DeserializationContext ctxt) throws IOException { 326 // not sure how this should work... 327 return (char[]) ctxt.handleUnexpectedToken(_valueClass, p); 328 } 329 330 @Override _concat(char[] oldValue, char[] newValue)331 protected char[] _concat(char[] oldValue, char[] newValue) { 332 int len1 = oldValue.length; 333 int len2 = newValue.length; 334 char[] result = Arrays.copyOf(oldValue, len1+len2); 335 System.arraycopy(newValue, 0, result, len1, len2); 336 return result; 337 } 338 } 339 340 /* 341 /********************************************************** 342 /* Actual deserializers: primivate array desers 343 /********************************************************** 344 */ 345 346 @JacksonStdImpl 347 final static class BooleanDeser 348 extends PrimitiveArrayDeserializers<boolean[]> 349 { 350 private static final long serialVersionUID = 1L; 351 BooleanDeser()352 public BooleanDeser() { super(boolean[].class); } BooleanDeser(BooleanDeser base, NullValueProvider nuller, Boolean unwrapSingle)353 protected BooleanDeser(BooleanDeser base, NullValueProvider nuller, Boolean unwrapSingle) { 354 super(base, nuller, unwrapSingle); 355 } 356 357 @Override withResolved(NullValueProvider nuller, Boolean unwrapSingle)358 protected PrimitiveArrayDeserializers<?> withResolved(NullValueProvider nuller, 359 Boolean unwrapSingle) { 360 return new BooleanDeser(this, nuller, unwrapSingle); 361 } 362 363 @Override _constructEmpty()364 protected boolean[] _constructEmpty() { 365 return new boolean[0]; 366 } 367 368 @Override deserialize(JsonParser p, DeserializationContext ctxt)369 public boolean[] deserialize(JsonParser p, DeserializationContext ctxt) 370 throws IOException 371 { 372 if (!p.isExpectedStartArrayToken()) { 373 return handleNonArray(p, ctxt); 374 } 375 ArrayBuilders.BooleanBuilder builder = ctxt.getArrayBuilders().getBooleanBuilder(); 376 boolean[] chunk = builder.resetAndStart(); 377 int ix = 0; 378 379 try { 380 JsonToken t; 381 while ((t = p.nextToken()) != JsonToken.END_ARRAY) { 382 boolean value; 383 if (t == JsonToken.VALUE_TRUE) { 384 value = true; 385 } else if (t == JsonToken.VALUE_FALSE) { 386 value = false; 387 } else if (t == JsonToken.VALUE_NULL) { 388 if (_nuller != null) { 389 _nuller.getNullValue(ctxt); 390 continue; 391 } 392 _verifyNullForPrimitive(ctxt); 393 value = false; 394 } else { 395 value = _parseBooleanPrimitive(p, ctxt); 396 } 397 if (ix >= chunk.length) { 398 chunk = builder.appendCompletedChunk(chunk, ix); 399 ix = 0; 400 } 401 chunk[ix++] = value; 402 } 403 } catch (Exception e) { 404 throw JsonMappingException.wrapWithPath(e, chunk, builder.bufferedSize() + ix); 405 } 406 return builder.completeAndClearBuffer(chunk, ix); 407 } 408 409 @Override handleSingleElementUnwrapped(JsonParser p, DeserializationContext ctxt)410 protected boolean[] handleSingleElementUnwrapped(JsonParser p, 411 DeserializationContext ctxt) throws IOException { 412 return new boolean[] { _parseBooleanPrimitive(p, ctxt) }; 413 } 414 415 @Override _concat(boolean[] oldValue, boolean[] newValue)416 protected boolean[] _concat(boolean[] oldValue, boolean[] newValue) { 417 int len1 = oldValue.length; 418 int len2 = newValue.length; 419 boolean[] result = Arrays.copyOf(oldValue, len1+len2); 420 System.arraycopy(newValue, 0, result, len1, len2); 421 return result; 422 } 423 } 424 425 /** 426 * When dealing with byte arrays we have one more alternative (compared 427 * to int/long/shorts): base64 encoded data. 428 */ 429 @JacksonStdImpl 430 final static class ByteDeser 431 extends PrimitiveArrayDeserializers<byte[]> 432 { 433 private static final long serialVersionUID = 1L; 434 ByteDeser()435 public ByteDeser() { super(byte[].class); } ByteDeser(ByteDeser base, NullValueProvider nuller,Boolean unwrapSingle)436 protected ByteDeser(ByteDeser base, NullValueProvider nuller,Boolean unwrapSingle) { 437 super(base, nuller, unwrapSingle); 438 } 439 440 @Override withResolved(NullValueProvider nuller, Boolean unwrapSingle)441 protected PrimitiveArrayDeserializers<?> withResolved(NullValueProvider nuller, 442 Boolean unwrapSingle) { 443 return new ByteDeser(this, nuller, unwrapSingle); 444 } 445 446 @Override _constructEmpty()447 protected byte[] _constructEmpty() { 448 return new byte[0]; 449 } 450 451 @Override // since 2.12 logicalType()452 public LogicalType logicalType() { 453 // 30-May-2020, tatu: while technically an array, logically contains 454 // binary data so... 455 return LogicalType.Binary; 456 } 457 458 @Override deserialize(JsonParser p, DeserializationContext ctxt)459 public byte[] deserialize(JsonParser p, DeserializationContext ctxt) throws IOException 460 { 461 JsonToken t = p.currentToken(); 462 463 // Most likely case: base64 encoded String? 464 if (t == JsonToken.VALUE_STRING) { 465 try { 466 return p.getBinaryValue(ctxt.getBase64Variant()); 467 } catch (JsonParseException e) { 468 // 25-Nov-2016, tatu: related to [databind#1425], try to convert 469 // to a more usable one, as it's not really a JSON-level parse 470 // exception, but rather binding from JSON String into base64 decoded 471 // binary data 472 String msg = e.getOriginalMessage(); 473 if (msg.contains("base64")) { 474 return (byte[]) ctxt.handleWeirdStringValue(byte[].class, 475 p.getText(), msg); 476 } 477 } 478 } 479 // 31-Dec-2009, tatu: Also may be hidden as embedded Object 480 if (t == JsonToken.VALUE_EMBEDDED_OBJECT) { 481 Object ob = p.getEmbeddedObject(); 482 if (ob == null) return null; 483 if (ob instanceof byte[]) { 484 return (byte[]) ob; 485 } 486 } 487 if (!p.isExpectedStartArrayToken()) { 488 return handleNonArray(p, ctxt); 489 } 490 ArrayBuilders.ByteBuilder builder = ctxt.getArrayBuilders().getByteBuilder(); 491 byte[] chunk = builder.resetAndStart(); 492 int ix = 0; 493 494 try { 495 while ((t = p.nextToken()) != JsonToken.END_ARRAY) { 496 // whether we should allow truncating conversions? 497 byte value; 498 if (t == JsonToken.VALUE_NUMBER_INT) { 499 value = p.getByteValue(); // note: may throw due to overflow 500 } else { 501 // should probably accept nulls as 0 502 if (t == JsonToken.VALUE_NULL) { 503 if (_nuller != null) { 504 _nuller.getNullValue(ctxt); 505 continue; 506 } 507 _verifyNullForPrimitive(ctxt); 508 value = (byte) 0; 509 } else { 510 value = _parseBytePrimitive(p, ctxt); 511 } 512 } 513 if (ix >= chunk.length) { 514 chunk = builder.appendCompletedChunk(chunk, ix); 515 ix = 0; 516 } 517 chunk[ix++] = value; 518 } 519 } catch (Exception e) { 520 throw JsonMappingException.wrapWithPath(e, chunk, builder.bufferedSize() + ix); 521 } 522 return builder.completeAndClearBuffer(chunk, ix); 523 } 524 525 @Override handleSingleElementUnwrapped(JsonParser p, DeserializationContext ctxt)526 protected byte[] handleSingleElementUnwrapped(JsonParser p, 527 DeserializationContext ctxt) throws IOException 528 { 529 byte value; 530 JsonToken t = p.currentToken(); 531 if (t == JsonToken.VALUE_NUMBER_INT) { 532 value = p.getByteValue(); // note: may throw due to overflow 533 } else { 534 // should probably accept nulls as 'false' 535 if (t == JsonToken.VALUE_NULL) { 536 if (_nuller != null) { 537 _nuller.getNullValue(ctxt); 538 return (byte[]) getEmptyValue(ctxt); 539 } 540 _verifyNullForPrimitive(ctxt); 541 return null; 542 } 543 Number n = (Number) ctxt.handleUnexpectedToken(_valueClass.getComponentType(), p); 544 value = n.byteValue(); 545 } 546 return new byte[] { value }; 547 } 548 549 @Override _concat(byte[] oldValue, byte[] newValue)550 protected byte[] _concat(byte[] oldValue, byte[] newValue) { 551 int len1 = oldValue.length; 552 int len2 = newValue.length; 553 byte[] result = Arrays.copyOf(oldValue, len1+len2); 554 System.arraycopy(newValue, 0, result, len1, len2); 555 return result; 556 } 557 } 558 559 @JacksonStdImpl 560 final static class ShortDeser 561 extends PrimitiveArrayDeserializers<short[]> 562 { 563 private static final long serialVersionUID = 1L; 564 ShortDeser()565 public ShortDeser() { super(short[].class); } ShortDeser(ShortDeser base, NullValueProvider nuller, Boolean unwrapSingle)566 protected ShortDeser(ShortDeser base, NullValueProvider nuller, Boolean unwrapSingle) { 567 super(base, nuller, unwrapSingle); 568 } 569 570 @Override withResolved(NullValueProvider nuller, Boolean unwrapSingle)571 protected PrimitiveArrayDeserializers<?> withResolved(NullValueProvider nuller, 572 Boolean unwrapSingle) { 573 return new ShortDeser(this, nuller, unwrapSingle); 574 } 575 576 @Override _constructEmpty()577 protected short[] _constructEmpty() { 578 return new short[0]; 579 } 580 581 @Override deserialize(JsonParser p, DeserializationContext ctxt)582 public short[] deserialize(JsonParser p, DeserializationContext ctxt) throws IOException 583 { 584 if (!p.isExpectedStartArrayToken()) { 585 return handleNonArray(p, ctxt); 586 } 587 ArrayBuilders.ShortBuilder builder = ctxt.getArrayBuilders().getShortBuilder(); 588 short[] chunk = builder.resetAndStart(); 589 int ix = 0; 590 591 try { 592 JsonToken t; 593 while ((t = p.nextToken()) != JsonToken.END_ARRAY) { 594 short value; 595 if (t == JsonToken.VALUE_NULL) { 596 if (_nuller != null) { 597 _nuller.getNullValue(ctxt); 598 continue; 599 } 600 _verifyNullForPrimitive(ctxt); 601 value = (short) 0; 602 } else { 603 value = _parseShortPrimitive(p, ctxt); 604 } 605 if (ix >= chunk.length) { 606 chunk = builder.appendCompletedChunk(chunk, ix); 607 ix = 0; 608 } 609 chunk[ix++] = value; 610 } 611 } catch (Exception e) { 612 throw JsonMappingException.wrapWithPath(e, chunk, builder.bufferedSize() + ix); 613 } 614 return builder.completeAndClearBuffer(chunk, ix); 615 } 616 617 @Override handleSingleElementUnwrapped(JsonParser p, DeserializationContext ctxt)618 protected short[] handleSingleElementUnwrapped(JsonParser p, 619 DeserializationContext ctxt) throws IOException { 620 return new short[] { _parseShortPrimitive(p, ctxt) }; 621 } 622 623 @Override _concat(short[] oldValue, short[] newValue)624 protected short[] _concat(short[] oldValue, short[] newValue) { 625 int len1 = oldValue.length; 626 int len2 = newValue.length; 627 short[] result = Arrays.copyOf(oldValue, len1+len2); 628 System.arraycopy(newValue, 0, result, len1, len2); 629 return result; 630 } 631 } 632 633 @JacksonStdImpl 634 final static class IntDeser 635 extends PrimitiveArrayDeserializers<int[]> 636 { 637 private static final long serialVersionUID = 1L; 638 639 public final static IntDeser instance = new IntDeser(); 640 IntDeser()641 public IntDeser() { super(int[].class); } IntDeser(IntDeser base, NullValueProvider nuller, Boolean unwrapSingle)642 protected IntDeser(IntDeser base, NullValueProvider nuller, Boolean unwrapSingle) { 643 super(base, nuller, unwrapSingle); 644 } 645 646 @Override withResolved(NullValueProvider nuller, Boolean unwrapSingle)647 protected PrimitiveArrayDeserializers<?> withResolved(NullValueProvider nuller, 648 Boolean unwrapSingle) { 649 return new IntDeser(this, nuller, unwrapSingle); 650 } 651 652 @Override _constructEmpty()653 protected int[] _constructEmpty() { 654 return new int[0]; 655 } 656 657 @Override deserialize(JsonParser p, DeserializationContext ctxt)658 public int[] deserialize(JsonParser p, DeserializationContext ctxt) throws IOException 659 { 660 if (!p.isExpectedStartArrayToken()) { 661 return handleNonArray(p, ctxt); 662 } 663 ArrayBuilders.IntBuilder builder = ctxt.getArrayBuilders().getIntBuilder(); 664 int[] chunk = builder.resetAndStart(); 665 int ix = 0; 666 667 try { 668 JsonToken t; 669 while ((t = p.nextToken()) != JsonToken.END_ARRAY) { 670 int value; 671 if (t == JsonToken.VALUE_NUMBER_INT) { 672 value = p.getIntValue(); 673 } else if (t == JsonToken.VALUE_NULL) { 674 if (_nuller != null) { 675 _nuller.getNullValue(ctxt); 676 continue; 677 } 678 _verifyNullForPrimitive(ctxt); 679 value = 0; 680 } else { 681 value = _parseIntPrimitive(p, ctxt); 682 } 683 if (ix >= chunk.length) { 684 chunk = builder.appendCompletedChunk(chunk, ix); 685 ix = 0; 686 } 687 chunk[ix++] = value; 688 } 689 } catch (Exception e) { 690 throw JsonMappingException.wrapWithPath(e, chunk, builder.bufferedSize() + ix); 691 } 692 return builder.completeAndClearBuffer(chunk, ix); 693 } 694 695 @Override handleSingleElementUnwrapped(JsonParser p, DeserializationContext ctxt)696 protected int[] handleSingleElementUnwrapped(JsonParser p, 697 DeserializationContext ctxt) throws IOException { 698 return new int[] { _parseIntPrimitive(p, ctxt) }; 699 } 700 701 @Override _concat(int[] oldValue, int[] newValue)702 protected int[] _concat(int[] oldValue, int[] newValue) { 703 int len1 = oldValue.length; 704 int len2 = newValue.length; 705 int[] result = Arrays.copyOf(oldValue, len1+len2); 706 System.arraycopy(newValue, 0, result, len1, len2); 707 return result; 708 } 709 } 710 711 @JacksonStdImpl 712 final static class LongDeser 713 extends PrimitiveArrayDeserializers<long[]> 714 { 715 private static final long serialVersionUID = 1L; 716 717 public final static LongDeser instance = new LongDeser(); 718 LongDeser()719 public LongDeser() { super(long[].class); } LongDeser(LongDeser base, NullValueProvider nuller, Boolean unwrapSingle)720 protected LongDeser(LongDeser base, NullValueProvider nuller, Boolean unwrapSingle) { 721 super(base, nuller, unwrapSingle); 722 } 723 724 @Override withResolved(NullValueProvider nuller, Boolean unwrapSingle)725 protected PrimitiveArrayDeserializers<?> withResolved(NullValueProvider nuller, 726 Boolean unwrapSingle) { 727 return new LongDeser(this, nuller, unwrapSingle); 728 } 729 730 @Override _constructEmpty()731 protected long[] _constructEmpty() { 732 return new long[0]; 733 } 734 735 @Override deserialize(JsonParser p, DeserializationContext ctxt)736 public long[] deserialize(JsonParser p, DeserializationContext ctxt) throws IOException 737 { 738 if (!p.isExpectedStartArrayToken()) { 739 return handleNonArray(p, ctxt); 740 } 741 ArrayBuilders.LongBuilder builder = ctxt.getArrayBuilders().getLongBuilder(); 742 long[] chunk = builder.resetAndStart(); 743 int ix = 0; 744 745 try { 746 JsonToken t; 747 while ((t = p.nextToken()) != JsonToken.END_ARRAY) { 748 long value; 749 if (t == JsonToken.VALUE_NUMBER_INT) { 750 value = p.getLongValue(); 751 } else if (t == JsonToken.VALUE_NULL) { 752 if (_nuller != null) { 753 _nuller.getNullValue(ctxt); 754 continue; 755 } 756 _verifyNullForPrimitive(ctxt); 757 value = 0L; 758 } else { 759 value = _parseLongPrimitive(p, ctxt); 760 } 761 if (ix >= chunk.length) { 762 chunk = builder.appendCompletedChunk(chunk, ix); 763 ix = 0; 764 } 765 chunk[ix++] = value; 766 } 767 } catch (Exception e) { 768 throw JsonMappingException.wrapWithPath(e, chunk, builder.bufferedSize() + ix); 769 } 770 return builder.completeAndClearBuffer(chunk, ix); 771 } 772 773 @Override handleSingleElementUnwrapped(JsonParser p, DeserializationContext ctxt)774 protected long[] handleSingleElementUnwrapped(JsonParser p, 775 DeserializationContext ctxt) throws IOException { 776 return new long[] { _parseLongPrimitive(p, ctxt) }; 777 } 778 779 @Override _concat(long[] oldValue, long[] newValue)780 protected long[] _concat(long[] oldValue, long[] newValue) { 781 int len1 = oldValue.length; 782 int len2 = newValue.length; 783 long[] result = Arrays.copyOf(oldValue, len1+len2); 784 System.arraycopy(newValue, 0, result, len1, len2); 785 return result; 786 } 787 } 788 789 @JacksonStdImpl 790 final static class FloatDeser 791 extends PrimitiveArrayDeserializers<float[]> 792 { 793 private static final long serialVersionUID = 1L; 794 FloatDeser()795 public FloatDeser() { super(float[].class); } FloatDeser(FloatDeser base, NullValueProvider nuller, Boolean unwrapSingle)796 protected FloatDeser(FloatDeser base, NullValueProvider nuller, Boolean unwrapSingle) { 797 super(base, nuller, unwrapSingle); 798 } 799 800 @Override withResolved(NullValueProvider nuller, Boolean unwrapSingle)801 protected PrimitiveArrayDeserializers<?> withResolved(NullValueProvider nuller, 802 Boolean unwrapSingle) { 803 return new FloatDeser(this, nuller, unwrapSingle); 804 } 805 806 @Override _constructEmpty()807 protected float[] _constructEmpty() { 808 return new float[0]; 809 } 810 811 @Override deserialize(JsonParser p, DeserializationContext ctxt)812 public float[] deserialize(JsonParser p, DeserializationContext ctxt) throws IOException 813 { 814 if (!p.isExpectedStartArrayToken()) { 815 return handleNonArray(p, ctxt); 816 } 817 ArrayBuilders.FloatBuilder builder = ctxt.getArrayBuilders().getFloatBuilder(); 818 float[] chunk = builder.resetAndStart(); 819 int ix = 0; 820 821 try { 822 JsonToken t; 823 while ((t = p.nextToken()) != JsonToken.END_ARRAY) { 824 // whether we should allow truncating conversions? 825 if (t == JsonToken.VALUE_NULL) { 826 if (_nuller != null) { 827 _nuller.getNullValue(ctxt); 828 continue; 829 } 830 } 831 float value = _parseFloatPrimitive(p, ctxt); 832 if (ix >= chunk.length) { 833 chunk = builder.appendCompletedChunk(chunk, ix); 834 ix = 0; 835 } 836 chunk[ix++] = value; 837 } 838 } catch (Exception e) { 839 throw JsonMappingException.wrapWithPath(e, chunk, builder.bufferedSize() + ix); 840 } 841 return builder.completeAndClearBuffer(chunk, ix); 842 } 843 844 @Override handleSingleElementUnwrapped(JsonParser p, DeserializationContext ctxt)845 protected float[] handleSingleElementUnwrapped(JsonParser p, 846 DeserializationContext ctxt) throws IOException { 847 return new float[] { _parseFloatPrimitive(p, ctxt) }; 848 } 849 850 @Override _concat(float[] oldValue, float[] newValue)851 protected float[] _concat(float[] oldValue, float[] newValue) { 852 int len1 = oldValue.length; 853 int len2 = newValue.length; 854 float[] result = Arrays.copyOf(oldValue, len1+len2); 855 System.arraycopy(newValue, 0, result, len1, len2); 856 return result; 857 } 858 } 859 860 @JacksonStdImpl 861 final static class DoubleDeser 862 extends PrimitiveArrayDeserializers<double[]> 863 { 864 private static final long serialVersionUID = 1L; 865 DoubleDeser()866 public DoubleDeser() { super(double[].class); } DoubleDeser(DoubleDeser base, NullValueProvider nuller, Boolean unwrapSingle)867 protected DoubleDeser(DoubleDeser base, NullValueProvider nuller, Boolean unwrapSingle) { 868 super(base, nuller, unwrapSingle); 869 } 870 871 @Override withResolved(NullValueProvider nuller, Boolean unwrapSingle)872 protected PrimitiveArrayDeserializers<?> withResolved(NullValueProvider nuller, 873 Boolean unwrapSingle) { 874 return new DoubleDeser(this, nuller, unwrapSingle); 875 } 876 877 @Override _constructEmpty()878 protected double[] _constructEmpty() { 879 return new double[0]; 880 } 881 882 @Override deserialize(JsonParser p, DeserializationContext ctxt)883 public double[] deserialize(JsonParser p, DeserializationContext ctxt) throws IOException 884 { 885 if (!p.isExpectedStartArrayToken()) { 886 return handleNonArray(p, ctxt); 887 } 888 ArrayBuilders.DoubleBuilder builder = ctxt.getArrayBuilders().getDoubleBuilder(); 889 double[] chunk = builder.resetAndStart(); 890 int ix = 0; 891 892 try { 893 JsonToken t; 894 while ((t = p.nextToken()) != JsonToken.END_ARRAY) { 895 if (t == JsonToken.VALUE_NULL) { 896 if (_nuller != null) { 897 _nuller.getNullValue(ctxt); 898 continue; 899 } 900 } 901 double value = _parseDoublePrimitive(p, ctxt); 902 if (ix >= chunk.length) { 903 chunk = builder.appendCompletedChunk(chunk, ix); 904 ix = 0; 905 } 906 chunk[ix++] = value; 907 } 908 } catch (Exception e) { 909 throw JsonMappingException.wrapWithPath(e, chunk, builder.bufferedSize() + ix); 910 } 911 return builder.completeAndClearBuffer(chunk, ix); 912 } 913 914 @Override handleSingleElementUnwrapped(JsonParser p, DeserializationContext ctxt)915 protected double[] handleSingleElementUnwrapped(JsonParser p, 916 DeserializationContext ctxt) throws IOException { 917 return new double[] { _parseDoublePrimitive(p, ctxt) }; 918 } 919 920 @Override _concat(double[] oldValue, double[] newValue)921 protected double[] _concat(double[] oldValue, double[] newValue) { 922 int len1 = oldValue.length; 923 int len2 = newValue.length; 924 double[] result = Arrays.copyOf(oldValue, len1+len2); 925 System.arraycopy(newValue, 0, result, len1, len2); 926 return result; 927 } 928 } 929 } 930