1 package com.fasterxml.jackson.databind.deser.std;
2
3 import java.io.IOException;
4 import java.util.*;
5
6 import com.fasterxml.jackson.annotation.JsonFormat;
7 import com.fasterxml.jackson.annotation.Nulls;
8 import com.fasterxml.jackson.core.*;
9 import com.fasterxml.jackson.core.exc.InputCoercionException;
10 import com.fasterxml.jackson.core.io.NumberInput;
11 import com.fasterxml.jackson.databind.*;
12 import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
13 import com.fasterxml.jackson.databind.deser.BeanDeserializerBase;
14 import com.fasterxml.jackson.databind.deser.NullValueProvider;
15 import com.fasterxml.jackson.databind.deser.SettableBeanProperty;
16 import com.fasterxml.jackson.databind.deser.ValueInstantiator;
17 import com.fasterxml.jackson.databind.deser.impl.NullsAsEmptyProvider;
18 import com.fasterxml.jackson.databind.deser.impl.NullsConstantProvider;
19 import com.fasterxml.jackson.databind.deser.impl.NullsFailProvider;
20 import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
21 import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
22 import com.fasterxml.jackson.databind.util.AccessPattern;
23 import com.fasterxml.jackson.databind.util.ClassUtil;
24 import com.fasterxml.jackson.databind.util.Converter;
25
26
31 public abstract class StdDeserializer<T>
32 extends JsonDeserializer<T>
33 implements java.io.Serializable
34 {
35 private static final long serialVersionUID = 1L;
36
37
44 protected final static int F_MASK_INT_COERCIONS =
45 DeserializationFeature.USE_BIG_INTEGER_FOR_INTS.getMask()
46 | DeserializationFeature.USE_LONG_FOR_INTS.getMask();
47
48
49 protected final static int F_MASK_ACCEPT_ARRAYS =
50 DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS.getMask() |
51 DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT.getMask();
52
53
59 final protected Class<?> _valueClass;
60
61 final protected JavaType _valueType;
62
63 protected StdDeserializer(Class<?> vc) {
64 _valueClass = vc;
65 _valueType = null;
66 }
67
68 protected StdDeserializer(JavaType valueType) {
69
70 _valueClass = (valueType == null) ? Object.class : valueType.getRawClass();
71 _valueType = valueType;
72 }
73
74
80 protected StdDeserializer(StdDeserializer<?> src) {
81 _valueClass = src._valueClass;
82 _valueType = src._valueType;
83 }
84
85
90
91 @Override
92 public Class<?> handledType() { return _valueClass; }
93
94
99
100
103 @Deprecated
104 public final Class<?> getValueClass() { return _valueClass; }
105
106
109 public JavaType getValueType() { return _valueType; }
110
111
124 public JavaType getValueType(DeserializationContext ctxt) {
125 if (_valueType != null) {
126 return _valueType;
127 }
128 return ctxt.constructType(_valueClass);
129 }
130
131
137 protected boolean isDefaultDeserializer(JsonDeserializer<?> deserializer) {
138 return ClassUtil.isJacksonStdImpl(deserializer);
139 }
140
141 protected boolean isDefaultKeyDeserializer(KeyDeserializer keyDeser) {
142 return ClassUtil.isJacksonStdImpl(keyDeser);
143 }
144
145
150
151
156 @Override
157 public Object deserializeWithType(JsonParser p, DeserializationContext ctxt,
158 TypeDeserializer typeDeserializer) throws IOException {
159 return typeDeserializer.deserializeTypedFromAny(p, ctxt);
160 }
161
162
169
170 @Deprecated
171 protected final boolean _parseBooleanPrimitive(JsonParser p, DeserializationContext ctxt) throws IOException {
172 return _parseBooleanPrimitive(ctxt, p, Boolean.TYPE);
173 }
174
175
176 protected final boolean _parseBooleanPrimitive(DeserializationContext ctxt,
177 JsonParser p, Class<?> targetType) throws IOException
178 {
179 JsonToken t = p.getCurrentToken();
180 if (t == JsonToken.VALUE_TRUE) return true;
181 if (t == JsonToken.VALUE_FALSE) return false;
182 if (t == JsonToken.VALUE_NULL) {
183 _verifyNullForPrimitive(ctxt);
184 return false;
185 }
186
187
188 if (t == JsonToken.VALUE_NUMBER_INT) {
189 return _parseBooleanFromInt(p, ctxt);
190 }
191
192 if (t == JsonToken.VALUE_STRING) {
193 String text = p.getText().trim();
194
195 if ("true".equals(text) || "True".equals(text)) {
196 return true;
197 }
198 if ("false".equals(text) || "False".equals(text)) {
199 return false;
200 }
201 if (_isEmptyOrTextualNull(text)) {
202 _verifyNullForPrimitiveCoercion(ctxt, text);
203 return false;
204 }
205 Boolean b = (Boolean) ctxt.handleWeirdStringValue(targetType, text,
206 "only \"true\" or \"false\" recognized");
207 return Boolean.TRUE.equals(b);
208 }
209
210 if (t == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
211 p.nextToken();
212 final boolean parsed = _parseBooleanPrimitive(ctxt, p, targetType);
213 _verifyEndArrayForSingle(p, ctxt);
214 return parsed;
215 }
216
217 return ((Boolean) ctxt.handleUnexpectedToken(targetType, p)).booleanValue();
218 }
219
220 protected boolean _parseBooleanFromInt(JsonParser p, DeserializationContext ctxt)
221 throws IOException
222 {
223
224
225
226
227 _verifyNumberForScalarCoercion(ctxt, p);
228
229
230 return !"0".equals(p.getText());
231 }
232
233 protected final byte _parseBytePrimitive(JsonParser p, DeserializationContext ctxt)
234 throws IOException
235 {
236 int value = _parseIntPrimitive(p, ctxt);
237
238 if (_byteOverflow(value)) {
239 Number v = (Number) ctxt.handleWeirdStringValue(_valueClass, String.valueOf(value),
240 "overflow, value cannot be represented as 8-bit value");
241 return _nonNullNumber(v).byteValue();
242 }
243 return (byte) value;
244 }
245
246 protected final short _parseShortPrimitive(JsonParser p, DeserializationContext ctxt)
247 throws IOException
248 {
249 int value = _parseIntPrimitive(p, ctxt);
250
251 if (_shortOverflow(value)) {
252 Number v = (Number) ctxt.handleWeirdStringValue(_valueClass, String.valueOf(value),
253 "overflow, value cannot be represented as 16-bit value");
254 return _nonNullNumber(v).shortValue();
255 }
256 return (short) value;
257 }
258
259 protected final int _parseIntPrimitive(JsonParser p, DeserializationContext ctxt)
260 throws IOException
261 {
262 if (p.hasToken(JsonToken.VALUE_NUMBER_INT)) {
263 return p.getIntValue();
264 }
265 switch (p.getCurrentTokenId()) {
266 case JsonTokenId.ID_STRING:
267 String text = p.getText().trim();
268 if (_isEmptyOrTextualNull(text)) {
269 _verifyNullForPrimitiveCoercion(ctxt, text);
270 return 0;
271 }
272 return _parseIntPrimitive(ctxt, text);
273 case JsonTokenId.ID_NUMBER_FLOAT:
274 if (!ctxt.isEnabled(DeserializationFeature.ACCEPT_FLOAT_AS_INT)) {
275 _failDoubleToIntCoercion(p, ctxt, "int");
276 }
277 return p.getValueAsInt();
278 case JsonTokenId.ID_NULL:
279 _verifyNullForPrimitive(ctxt);
280 return 0;
281 case JsonTokenId.ID_START_ARRAY:
282 if (ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
283 p.nextToken();
284 final int parsed = _parseIntPrimitive(p, ctxt);
285 _verifyEndArrayForSingle(p, ctxt);
286 return parsed;
287 }
288 break;
289 default:
290 }
291
292 return ((Number) ctxt.handleUnexpectedToken(_valueClass, p)).intValue();
293 }
294
295
298 protected final int _parseIntPrimitive(DeserializationContext ctxt, String text) throws IOException
299 {
300 try {
301 if (text.length() > 9) {
302 long l = Long.parseLong(text);
303 if (_intOverflow(l)) {
304 Number v = (Number) ctxt.handleWeirdStringValue(_valueClass, text,
305 "Overflow: numeric value (%s) out of range of int (%d -%d)",
306 text, Integer.MIN_VALUE, Integer.MAX_VALUE);
307 return _nonNullNumber(v).intValue();
308 }
309 return (int) l;
310 }
311 return NumberInput.parseInt(text);
312 } catch (IllegalArgumentException iae) {
313 Number v = (Number) ctxt.handleWeirdStringValue(_valueClass, text,
314 "not a valid int value");
315 return _nonNullNumber(v).intValue();
316 }
317 }
318
319 protected final long _parseLongPrimitive(JsonParser p, DeserializationContext ctxt)
320 throws IOException
321 {
322 if (p.hasToken(JsonToken.VALUE_NUMBER_INT)) {
323 return p.getLongValue();
324 }
325 switch (p.getCurrentTokenId()) {
326 case JsonTokenId.ID_STRING:
327 String text = p.getText().trim();
328 if (_isEmptyOrTextualNull(text)) {
329 _verifyNullForPrimitiveCoercion(ctxt, text);
330 return 0L;
331 }
332 return _parseLongPrimitive(ctxt, text);
333 case JsonTokenId.ID_NUMBER_FLOAT:
334 if (!ctxt.isEnabled(DeserializationFeature.ACCEPT_FLOAT_AS_INT)) {
335 _failDoubleToIntCoercion(p, ctxt, "long");
336 }
337 return p.getValueAsLong();
338 case JsonTokenId.ID_NULL:
339 _verifyNullForPrimitive(ctxt);
340 return 0L;
341 case JsonTokenId.ID_START_ARRAY:
342 if (ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
343 p.nextToken();
344 final long parsed = _parseLongPrimitive(p, ctxt);
345 _verifyEndArrayForSingle(p, ctxt);
346 return parsed;
347 }
348 break;
349 }
350 return ((Number) ctxt.handleUnexpectedToken(_valueClass, p)).longValue();
351 }
352
353
356 protected final long _parseLongPrimitive(DeserializationContext ctxt, String text) throws IOException
357 {
358 try {
359 return NumberInput.parseLong(text);
360 } catch (IllegalArgumentException iae) { }
361 {
362 Number v = (Number) ctxt.handleWeirdStringValue(_valueClass, text,
363 "not a valid long value");
364 return _nonNullNumber(v).longValue();
365 }
366 }
367
368 protected final float _parseFloatPrimitive(JsonParser p, DeserializationContext ctxt)
369 throws IOException
370 {
371 if (p.hasToken(JsonToken.VALUE_NUMBER_FLOAT)) {
372 return p.getFloatValue();
373 }
374 switch (p.getCurrentTokenId()) {
375 case JsonTokenId.ID_STRING:
376 String text = p.getText().trim();
377 if (_isEmptyOrTextualNull(text)) {
378 _verifyNullForPrimitiveCoercion(ctxt, text);
379 return 0.0f;
380 }
381 return _parseFloatPrimitive(ctxt, text);
382 case JsonTokenId.ID_NUMBER_INT:
383 return p.getFloatValue();
384 case JsonTokenId.ID_NULL:
385 _verifyNullForPrimitive(ctxt);
386 return 0.0f;
387 case JsonTokenId.ID_START_ARRAY:
388 if (ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
389 p.nextToken();
390 final float parsed = _parseFloatPrimitive(p, ctxt);
391 _verifyEndArrayForSingle(p, ctxt);
392 return parsed;
393 }
394 break;
395 }
396
397 return ((Number) ctxt.handleUnexpectedToken(_valueClass, p)).floatValue();
398 }
399
400
403 protected final float _parseFloatPrimitive(DeserializationContext ctxt, String text)
404 throws IOException
405 {
406 switch (text.charAt(0)) {
407 case 'I':
408 if (_isPosInf(text)) {
409 return Float.POSITIVE_INFINITY;
410 }
411 break;
412 case 'N':
413 if (_isNaN(text)) { return Float.NaN; }
414 break;
415 case '-':
416 if (_isNegInf(text)) {
417 return Float.NEGATIVE_INFINITY;
418 }
419 break;
420 }
421 try {
422 return Float.parseFloat(text);
423 } catch (IllegalArgumentException iae) { }
424 Number v = (Number) ctxt.handleWeirdStringValue(_valueClass, text,
425 "not a valid float value");
426 return _nonNullNumber(v).floatValue();
427 }
428
429 protected final double _parseDoublePrimitive(JsonParser p, DeserializationContext ctxt)
430 throws IOException
431 {
432 if (p.hasToken(JsonToken.VALUE_NUMBER_FLOAT)) {
433 return p.getDoubleValue();
434 }
435 switch (p.getCurrentTokenId()) {
436 case JsonTokenId.ID_STRING:
437 String text = p.getText().trim();
438 if (_isEmptyOrTextualNull(text)) {
439 _verifyNullForPrimitiveCoercion(ctxt, text);
440 return 0.0;
441 }
442 return _parseDoublePrimitive(ctxt, text);
443 case JsonTokenId.ID_NUMBER_INT:
444 return p.getDoubleValue();
445 case JsonTokenId.ID_NULL:
446 _verifyNullForPrimitive(ctxt);
447 return 0.0;
448 case JsonTokenId.ID_START_ARRAY:
449 if (ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
450 p.nextToken();
451 final double parsed = _parseDoublePrimitive(p, ctxt);
452 _verifyEndArrayForSingle(p, ctxt);
453 return parsed;
454 }
455 break;
456 }
457
458 return ((Number) ctxt.handleUnexpectedToken(_valueClass, p)).doubleValue();
459 }
460
461
464 protected final double _parseDoublePrimitive(DeserializationContext ctxt, String text)
465 throws IOException
466 {
467 switch (text.charAt(0)) {
468 case 'I':
469 if (_isPosInf(text)) {
470 return Double.POSITIVE_INFINITY;
471 }
472 break;
473 case 'N':
474 if (_isNaN(text)) {
475 return Double.NaN;
476 }
477 break;
478 case '-':
479 if (_isNegInf(text)) {
480 return Double.NEGATIVE_INFINITY;
481 }
482 break;
483 }
484 try {
485 return parseDouble(text);
486 } catch (IllegalArgumentException iae) { }
487 Number v = (Number) ctxt.handleWeirdStringValue(_valueClass, text,
488 "not a valid double value (as String to convert)");
489 return _nonNullNumber(v).doubleValue();
490 }
491
492 protected java.util.Date _parseDate(JsonParser p, DeserializationContext ctxt)
493 throws IOException
494 {
495 switch (p.getCurrentTokenId()) {
496 case JsonTokenId.ID_STRING:
497 return _parseDate(p.getText().trim(), ctxt);
498 case JsonTokenId.ID_NUMBER_INT:
499 {
500 long ts;
501 try {
502 ts = p.getLongValue();
503
504
505 } catch (JsonParseException | InputCoercionException e) {
506 Number v = (Number) ctxt.handleWeirdNumberValue(_valueClass, p.getNumberValue(),
507 "not a valid 64-bit long for creating `java.util.Date`");
508 ts = v.longValue();
509 }
510 return new java.util.Date(ts);
511 }
512 case JsonTokenId.ID_NULL:
513 return (java.util.Date) getNullValue(ctxt);
514 case JsonTokenId.ID_START_ARRAY:
515 return _parseDateFromArray(p, ctxt);
516 }
517 return (java.util.Date) ctxt.handleUnexpectedToken(_valueClass, p);
518 }
519
520
521 protected java.util.Date _parseDateFromArray(JsonParser p, DeserializationContext ctxt)
522 throws IOException
523 {
524 JsonToken t;
525 if (ctxt.hasSomeOfFeatures(F_MASK_ACCEPT_ARRAYS)) {
526 t = p.nextToken();
527 if (t == JsonToken.END_ARRAY) {
528 if (ctxt.isEnabled(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT)) {
529 return (java.util.Date) getNullValue(ctxt);
530 }
531 }
532 if (ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
533 final Date parsed = _parseDate(p, ctxt);
534 _verifyEndArrayForSingle(p, ctxt);
535 return parsed;
536 }
537 } else {
538 t = p.getCurrentToken();
539 }
540 return (java.util.Date) ctxt.handleUnexpectedToken(_valueClass, t, p, null);
541 }
542
543
546 protected java.util.Date _parseDate(String value, DeserializationContext ctxt)
547 throws IOException
548 {
549 try {
550
551 if (_isEmptyOrTextualNull(value)) {
552 return (java.util.Date) getNullValue(ctxt);
553 }
554 return ctxt.parseDate(value);
555 } catch (IllegalArgumentException iae) {
556 return (java.util.Date) ctxt.handleWeirdStringValue(_valueClass, value,
557 "not a valid representation (error: %s)",
558 ClassUtil.exceptionMessage(iae));
559 }
560 }
561
562
566 protected final static double parseDouble(String numStr) throws NumberFormatException
567 {
568
569 if (NumberInput.NASTY_SMALL_DOUBLE.equals(numStr)) {
570 return Double.MIN_NORMAL;
571 }
572 return Double.parseDouble(numStr);
573 }
574
575
581 protected final String _parseString(JsonParser p, DeserializationContext ctxt) throws IOException
582 {
583 JsonToken t = p.getCurrentToken();
584 if (t == JsonToken.VALUE_STRING) {
585 return p.getText();
586 }
587
588 if (t == JsonToken.VALUE_EMBEDDED_OBJECT) {
589 Object ob = p.getEmbeddedObject();
590 if (ob instanceof byte[]) {
591 return ctxt.getBase64Variant().encode((byte[]) ob, false);
592 }
593 if (ob == null) {
594 return null;
595 }
596
597 return ob.toString();
598 }
599
600
601
602
611 String value = p.getValueAsString();
612 if (value != null) {
613 return value;
614 }
615 return (String) ctxt.handleUnexpectedToken(String.class, p);
616 }
617
618
624 @SuppressWarnings("unchecked")
625 protected T _deserializeFromEmpty(JsonParser p, DeserializationContext ctxt)
626 throws IOException
627 {
628 JsonToken t = p.getCurrentToken();
629 if (t == JsonToken.START_ARRAY) {
630 if (ctxt.isEnabled(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT)) {
631 t = p.nextToken();
632 if (t == JsonToken.END_ARRAY) {
633 return null;
634 }
635 return (T) ctxt.handleUnexpectedToken(handledType(), p);
636 }
637 } else if (t == JsonToken.VALUE_STRING) {
638 if (ctxt.isEnabled(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT)) {
639 String str = p.getText().trim();
640 if (str.isEmpty()) {
641 return null;
642 }
643 }
644 }
645 return (T) ctxt.handleUnexpectedToken(handledType(), p);
646 }
647
648
655 protected boolean _hasTextualNull(String value) {
656 return "null".equals(value);
657 }
658
659
662 protected boolean _isEmptyOrTextualNull(String value) {
663 return value.isEmpty() || "null".equals(value);
664 }
665
666 protected final boolean _isNegInf(String text) {
667 return "-Infinity".equals(text) || "-INF".equals(text);
668 }
669
670 protected final boolean _isPosInf(String text) {
671 return "Infinity".equals(text) || "INF".equals(text);
672 }
673
674 protected final boolean _isNaN(String text) { return "NaN".equals(text); }
675
676
682
683
699 protected T _deserializeFromArray(JsonParser p, DeserializationContext ctxt) throws IOException
700 {
701 JsonToken t;
702 if (ctxt.hasSomeOfFeatures(F_MASK_ACCEPT_ARRAYS)) {
703 t = p.nextToken();
704 if (t == JsonToken.END_ARRAY) {
705 if (ctxt.isEnabled(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT)) {
706 return getNullValue(ctxt);
707 }
708 }
709 if (ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
710 final T parsed = deserialize(p, ctxt);
711 if (p.nextToken() != JsonToken.END_ARRAY) {
712 handleMissingEndArrayForSingle(p, ctxt);
713 }
714 return parsed;
715 }
716 } else {
717 t = p.getCurrentToken();
718 }
719 @SuppressWarnings("unchecked")
720 T result = (T) ctxt.handleUnexpectedToken(getValueType(ctxt), p.getCurrentToken(), p, null);
721 return result;
722 }
723
724
732 protected T _deserializeWrappedValue(JsonParser p, DeserializationContext ctxt) throws IOException
733 {
734
735
736 if (p.hasToken(JsonToken.START_ARRAY)) {
737 String msg = String.format(
738 "Cannot deserialize instance of %s out of %s token: nested Arrays not allowed with %s",
739 ClassUtil.nameOf(_valueClass), JsonToken.START_ARRAY,
740 "DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS");
741 @SuppressWarnings("unchecked")
742 T result = (T) ctxt.handleUnexpectedToken(getValueType(ctxt), p.getCurrentToken(), p, msg);
743 return result;
744 }
745 return (T) deserialize(p, ctxt);
746 }
747
748
753
754 protected void _failDoubleToIntCoercion(JsonParser p, DeserializationContext ctxt,
755 String type) throws IOException
756 {
757 ctxt.reportInputMismatch(handledType(),
758 "Cannot coerce a floating-point value ('%s') into %s (enable `DeserializationFeature.ACCEPT_FLOAT_AS_INT` to allow)",
759 p.getValueAsString(), type);
760 }
761
762
773 protected Object _coerceIntegral(JsonParser p, DeserializationContext ctxt) throws IOException
774 {
775 int feats = ctxt.getDeserializationFeatures();
776 if (DeserializationFeature.USE_BIG_INTEGER_FOR_INTS.enabledIn(feats)) {
777 return p.getBigIntegerValue();
778 }
779 if (DeserializationFeature.USE_LONG_FOR_INTS.enabledIn(feats)) {
780 return p.getLongValue();
781 }
782 return p.getBigIntegerValue();
783 }
784
785
791 protected Object _coerceNullToken(DeserializationContext ctxt, boolean isPrimitive) throws JsonMappingException
792 {
793 if (isPrimitive) {
794 _verifyNullForPrimitive(ctxt);
795 }
796 return getNullValue(ctxt);
797 }
798
799
804 protected Object _coerceTextualNull(DeserializationContext ctxt, boolean isPrimitive) throws JsonMappingException
805 {
806 Enum<?> feat;
807 boolean enable;
808
809 if (!ctxt.isEnabled(MapperFeature.ALLOW_COERCION_OF_SCALARS)) {
810 feat = MapperFeature.ALLOW_COERCION_OF_SCALARS;
811 enable = true;
812 } else if (isPrimitive && ctxt.isEnabled(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES)) {
813 feat = DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES;
814 enable = false;
815 } else {
816 return getNullValue(ctxt);
817 }
818 _reportFailedNullCoerce(ctxt, enable, feat, "String \"null\"");
819 return null;
820 }
821
822
827 protected Object _coerceEmptyString(DeserializationContext ctxt, boolean isPrimitive) throws JsonMappingException
828 {
829 Enum<?> feat;
830 boolean enable;
831
832 if (!ctxt.isEnabled(MapperFeature.ALLOW_COERCION_OF_SCALARS)) {
833 feat = MapperFeature.ALLOW_COERCION_OF_SCALARS;
834 enable = true;
835 } else if (isPrimitive && ctxt.isEnabled(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES)) {
836 feat = DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES;
837 enable = false;
838 } else {
839 return getNullValue(ctxt);
840 }
841 _reportFailedNullCoerce(ctxt, enable, feat, "empty String (\"\")");
842 return null;
843 }
844
845
846 protected final void _verifyNullForPrimitive(DeserializationContext ctxt) throws JsonMappingException
847 {
848 if (ctxt.isEnabled(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES)) {
849 ctxt.reportInputMismatch(this,
850 "Cannot coerce `null` %s (disable `DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES` to allow)",
851 _coercedTypeDesc());
852 }
853 }
854
855
856
857 protected final void _verifyNullForPrimitiveCoercion(DeserializationContext ctxt, String str) throws JsonMappingException
858 {
859 Enum<?> feat;
860 boolean enable;
861
862 if (!ctxt.isEnabled(MapperFeature.ALLOW_COERCION_OF_SCALARS)) {
863 feat = MapperFeature.ALLOW_COERCION_OF_SCALARS;
864 enable = true;
865 } else if (ctxt.isEnabled(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES)) {
866 feat = DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES;
867 enable = false;
868 } else {
869 return;
870 }
871 String strDesc = str.isEmpty() ? "empty String (\"\")" : String.format("String \"%s\"", str);
872 _reportFailedNullCoerce(ctxt, enable, feat, strDesc);
873 }
874
875
876
877 protected final void _verifyNullForScalarCoercion(DeserializationContext ctxt, String str) throws JsonMappingException
878 {
879 if (!ctxt.isEnabled(MapperFeature.ALLOW_COERCION_OF_SCALARS)) {
880 String strDesc = str.isEmpty() ? "empty String (\"\")" : String.format("String \"%s\"", str);
881 _reportFailedNullCoerce(ctxt, true, MapperFeature.ALLOW_COERCION_OF_SCALARS, strDesc);
882 }
883 }
884
885
886 protected void _verifyStringForScalarCoercion(DeserializationContext ctxt, String str) throws JsonMappingException
887 {
888 MapperFeature feat = MapperFeature.ALLOW_COERCION_OF_SCALARS;
889 if (!ctxt.isEnabled(feat)) {
890 ctxt.reportInputMismatch(this, "Cannot coerce String \"%s\" %s (enable `%s.%s` to allow)",
891 str, _coercedTypeDesc(), feat.getClass().getSimpleName(), feat.name());
892 }
893 }
894
895
896 protected void _verifyNumberForScalarCoercion(DeserializationContext ctxt, JsonParser p) throws IOException
897 {
898 MapperFeature feat = MapperFeature.ALLOW_COERCION_OF_SCALARS;
899 if (!ctxt.isEnabled(feat)) {
900
901
902 String valueDesc = p.getText();
903 ctxt.reportInputMismatch(this, "Cannot coerce Number (%s) %s (enable `%s.%s` to allow)",
904 valueDesc, _coercedTypeDesc(), feat.getClass().getSimpleName(), feat.name());
905 }
906 }
907
908 protected void _reportFailedNullCoerce(DeserializationContext ctxt, boolean state, Enum<?> feature,
909 String inputDesc) throws JsonMappingException
910 {
911 String enableDesc = state ? "enable" : "disable";
912 ctxt.reportInputMismatch(this, "Cannot coerce %s to Null value %s (%s `%s.%s` to allow)",
913 inputDesc, _coercedTypeDesc(), enableDesc, feature.getClass().getSimpleName(), feature.name());
914 }
915
916
925 protected String _coercedTypeDesc() {
926 boolean structured;
927 String typeDesc;
928
929 JavaType t = getValueType();
930 if ((t != null) && !t.isPrimitive()) {
931 structured = (t.isContainerType() || t.isReferenceType());
932
933 typeDesc = "'"+t.toString()+"'";
934 } else {
935 Class<?> cls = handledType();
936 structured = cls.isArray() || Collection.class.isAssignableFrom(cls)
937 || Map.class.isAssignableFrom(cls);
938 typeDesc = ClassUtil.nameOf(cls);
939 }
940 if (structured) {
941 return "as content of type "+typeDesc;
942 }
943 return "for type "+typeDesc;
944 }
945
946
951
952
961 protected JsonDeserializer<Object> findDeserializer(DeserializationContext ctxt,
962 JavaType type, BeanProperty property)
963 throws JsonMappingException
964 {
965 return ctxt.findContextualValueDeserializer(type, property);
966 }
967
968
972 protected final boolean _isIntNumber(String text)
973 {
974 final int len = text.length();
975 if (len > 0) {
976 char c = text.charAt(0);
977
978 int i = (c == '-' || c == '+') ? 1 : 0;
979 for (; i < len; ++i) {
980 int ch = text.charAt(i);
981 if (ch > '9' || ch < '0') {
982 return false;
983 }
984 }
985 return true;
986 }
987 return false;
988 }
989
990
995
996
1006 protected JsonDeserializer<?> findConvertingContentDeserializer(DeserializationContext ctxt,
1007 BeanProperty prop, JsonDeserializer<?> existingDeserializer)
1008 throws JsonMappingException
1009 {
1010 final AnnotationIntrospector intr = ctxt.getAnnotationIntrospector();
1011 if (_neitherNull(intr, prop)) {
1012 AnnotatedMember member = prop.getMember();
1013 if (member != null) {
1014 Object convDef = intr.findDeserializationContentConverter(member);
1015 if (convDef != null) {
1016 Converter<Object,Object> conv = ctxt.converterInstance(prop.getMember(), convDef);
1017 JavaType delegateType = conv.getInputType(ctxt.getTypeFactory());
1018 if (existingDeserializer == null) {
1019 existingDeserializer = ctxt.findContextualValueDeserializer(delegateType, prop);
1020 }
1021 return new StdDelegatingDeserializer<Object>(conv, delegateType, existingDeserializer);
1022 }
1023 }
1024 }
1025 return existingDeserializer;
1026 }
1027
1028
1033
1034
1043 protected JsonFormat.Value findFormatOverrides(DeserializationContext ctxt,
1044 BeanProperty prop, Class<?> typeForDefaults)
1045 {
1046 if (prop != null) {
1047 return prop.findPropertyFormat(ctxt.getConfig(), typeForDefaults);
1048 }
1049
1050 return ctxt.getDefaultPropertyFormat(typeForDefaults);
1051 }
1052
1053
1063 protected Boolean findFormatFeature(DeserializationContext ctxt,
1064 BeanProperty prop, Class<?> typeForDefaults, JsonFormat.Feature feat)
1065 {
1066 JsonFormat.Value format = findFormatOverrides(ctxt, prop, typeForDefaults);
1067 if (format != null) {
1068 return format.getFeature(feat);
1069 }
1070 return null;
1071 }
1072
1073
1080 protected final NullValueProvider findValueNullProvider(DeserializationContext ctxt,
1081 SettableBeanProperty prop, PropertyMetadata propMetadata)
1082 throws JsonMappingException
1083 {
1084 if (prop != null) {
1085 return _findNullProvider(ctxt, prop, propMetadata.getValueNulls(),
1086 prop.getValueDeserializer());
1087 }
1088 return null;
1089 }
1090
1091
1099 protected NullValueProvider findContentNullProvider(DeserializationContext ctxt,
1100 BeanProperty prop, JsonDeserializer<?> valueDeser)
1101 throws JsonMappingException
1102 {
1103 final Nulls nulls = findContentNullStyle(ctxt, prop);
1104 if (nulls == Nulls.SKIP) {
1105 return NullsConstantProvider.skipper();
1106 }
1107
1108
1109 if (nulls == Nulls.FAIL) {
1110 if (prop == null) {
1111 JavaType type = ctxt.constructType(valueDeser.handledType());
1112
1113 if (type.isContainerType()) {
1114 type = type.getContentType();
1115 }
1116 return NullsFailProvider.constructForRootValue(type);
1117 }
1118 return NullsFailProvider.constructForProperty(prop, prop.getType().getContentType());
1119 }
1120
1121 NullValueProvider prov = _findNullProvider(ctxt, prop, nulls, valueDeser);
1122 if (prov != null) {
1123 return prov;
1124 }
1125 return valueDeser;
1126 }
1127
1128 protected Nulls findContentNullStyle(DeserializationContext ctxt, BeanProperty prop)
1129 throws JsonMappingException
1130 {
1131 if (prop != null) {
1132 return prop.getMetadata().getContentNulls();
1133 }
1134 return null;
1135 }
1136
1137
1138 protected final NullValueProvider _findNullProvider(DeserializationContext ctxt,
1139 BeanProperty prop, Nulls nulls, JsonDeserializer<?> valueDeser)
1140 throws JsonMappingException
1141 {
1142 if (nulls == Nulls.FAIL) {
1143 if (prop == null) {
1144 return NullsFailProvider.constructForRootValue(ctxt.constructType(valueDeser.handledType()));
1145 }
1146 return NullsFailProvider.constructForProperty(prop);
1147 }
1148 if (nulls == Nulls.AS_EMPTY) {
1149
1150
1151 if (valueDeser == null) {
1152 return null;
1153 }
1154
1155
1156
1157
1158 if (valueDeser instanceof BeanDeserializerBase) {
1159 ValueInstantiator vi = ((BeanDeserializerBase) valueDeser).getValueInstantiator();
1160 if (!vi.canCreateUsingDefault()) {
1161 final JavaType type = prop.getType();
1162 ctxt.reportBadDefinition(type,
1163 String.format("Cannot create empty instance of %s, no default Creator", type));
1164 }
1165 }
1166
1167 {
1168 AccessPattern access = valueDeser.getEmptyAccessPattern();
1169 if (access == AccessPattern.ALWAYS_NULL) {
1170 return NullsConstantProvider.nuller();
1171 }
1172 if (access == AccessPattern.CONSTANT) {
1173 return NullsConstantProvider.forValue(valueDeser.getEmptyValue(ctxt));
1174 }
1175 }
1176 return new NullsAsEmptyProvider(valueDeser);
1177 }
1178 if (nulls == Nulls.SKIP) {
1179 return NullsConstantProvider.skipper();
1180 }
1181 return null;
1182 }
1183
1184
1189
1190
1204 protected void handleUnknownProperty(JsonParser p, DeserializationContext ctxt,
1205 Object instanceOrClass, String propName)
1206 throws IOException
1207 {
1208 if (instanceOrClass == null) {
1209 instanceOrClass = handledType();
1210 }
1211
1212 if (ctxt.handleUnknownProperty(p, this, instanceOrClass, propName)) {
1213 return;
1214 }
1215
1218 p.skipChildren();
1219 }
1220
1221 protected void handleMissingEndArrayForSingle(JsonParser p, DeserializationContext ctxt)
1222 throws IOException
1223 {
1224 ctxt.reportWrongTokenException(this, JsonToken.END_ARRAY,
1225 "Attempted to unwrap '%s' value from an array (with `DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS`) but it contains more than one value",
1226 handledType().getName());
1227
1228
1229 }
1230
1231 protected void _verifyEndArrayForSingle(JsonParser p, DeserializationContext ctxt) throws IOException
1232 {
1233 JsonToken t = p.nextToken();
1234 if (t != JsonToken.END_ARRAY) {
1235 handleMissingEndArrayForSingle(p, ctxt);
1236 }
1237 }
1238
1239
1244
1245
1248 protected final static boolean _neitherNull(Object a, Object b) {
1249 return (a != null) && (b != null);
1250 }
1251
1252
1255 protected final boolean _byteOverflow(int value) {
1256
1257
1258 return (value < Byte.MIN_VALUE || value > 255);
1259 }
1260
1261
1264 protected final boolean _shortOverflow(int value) {
1265 return (value < Short.MIN_VALUE || value > Short.MAX_VALUE);
1266 }
1267
1268
1271 protected final boolean _intOverflow(long value) {
1272 return (value < Integer.MIN_VALUE || value > Integer.MAX_VALUE);
1273 }
1274
1275
1278 protected Number _nonNullNumber(Number n) {
1279 if (n == null) {
1280 n = Integer.valueOf(0);
1281 }
1282 return n;
1283 }
1284 }
1285