• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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