1 package com.fasterxml.jackson.databind.deser.std;
2
3 import java.io.IOException;
4 import java.math.BigDecimal;
5 import java.math.BigInteger;
6 import java.util.HashSet;
7
8 import com.fasterxml.jackson.core.*;
9 import com.fasterxml.jackson.core.io.NumberInput;
10 import com.fasterxml.jackson.databind.*;
11 import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
12 import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
13 import com.fasterxml.jackson.databind.util.AccessPattern;
14
15
22 public class NumberDeserializers
23 {
24 private final static HashSet<String> _classNames = new HashSet<String>();
25 static {
26
27 Class<?>[] numberTypes = new Class<?>[] {
28 Boolean.class,
29 Byte.class,
30 Short.class,
31 Character.class,
32 Integer.class,
33 Long.class,
34 Float.class,
35 Double.class,
36
37 Number.class, BigDecimal.class, BigInteger.class
38 };
39 for (Class<?> cls : numberTypes) {
40 _classNames.add(cls.getName());
41 }
42 }
43
44 public static JsonDeserializer<?> find(Class<?> rawType, String clsName) {
45 if (rawType.isPrimitive()) {
46 if (rawType == Integer.TYPE) {
47 return IntegerDeserializer.primitiveInstance;
48 }
49 if (rawType == Boolean.TYPE) {
50 return BooleanDeserializer.primitiveInstance;
51 }
52 if (rawType == Long.TYPE) {
53 return LongDeserializer.primitiveInstance;
54 }
55 if (rawType == Double.TYPE) {
56 return DoubleDeserializer.primitiveInstance;
57 }
58 if (rawType == Character.TYPE) {
59 return CharacterDeserializer.primitiveInstance;
60 }
61 if (rawType == Byte.TYPE) {
62 return ByteDeserializer.primitiveInstance;
63 }
64 if (rawType == Short.TYPE) {
65 return ShortDeserializer.primitiveInstance;
66 }
67 if (rawType == Float.TYPE) {
68 return FloatDeserializer.primitiveInstance;
69 }
70
71
72 if (rawType == Void.TYPE) {
73 return NullifyingDeserializer.instance;
74 }
75 } else if (_classNames.contains(clsName)) {
76
77 if (rawType == Integer.class) {
78 return IntegerDeserializer.wrapperInstance;
79 }
80 if (rawType == Boolean.class) {
81 return BooleanDeserializer.wrapperInstance;
82 }
83 if (rawType == Long.class) {
84 return LongDeserializer.wrapperInstance;
85 }
86 if (rawType == Double.class) {
87 return DoubleDeserializer.wrapperInstance;
88 }
89 if (rawType == Character.class) {
90 return CharacterDeserializer.wrapperInstance;
91 }
92 if (rawType == Byte.class) {
93 return ByteDeserializer.wrapperInstance;
94 }
95 if (rawType == Short.class) {
96 return ShortDeserializer.wrapperInstance;
97 }
98 if (rawType == Float.class) {
99 return FloatDeserializer.wrapperInstance;
100 }
101 if (rawType == Number.class) {
102 return NumberDeserializer.instance;
103 }
104 if (rawType == BigDecimal.class) {
105 return BigDecimalDeserializer.instance;
106 }
107 if (rawType == BigInteger.class) {
108 return BigIntegerDeserializer.instance;
109 }
110 } else {
111 return null;
112 }
113
114 throw new IllegalArgumentException("Internal error: can't find deserializer for "+rawType.getName());
115 }
116
117
123
124 protected abstract static class PrimitiveOrWrapperDeserializer<T>
125 extends StdScalarDeserializer<T>
126 {
127 private static final long serialVersionUID = 1L;
128
129 protected final T _nullValue;
130
131
132 protected final T _emptyValue;
133
134 protected final boolean _primitive;
135
136 protected PrimitiveOrWrapperDeserializer(Class<T> vc, T nvl, T empty) {
137 super(vc);
138 _nullValue = nvl;
139 _emptyValue = empty;
140 _primitive = vc.isPrimitive();
141 }
142
143 @Override
144 public AccessPattern getNullAccessPattern() {
145
146
147 if (_primitive) {
148 return AccessPattern.DYNAMIC;
149 }
150 if (_nullValue == null) {
151 return AccessPattern.ALWAYS_NULL;
152 }
153 return AccessPattern.CONSTANT;
154 }
155
156 @Override
157 public final T getNullValue(DeserializationContext ctxt) throws JsonMappingException {
158
159
160 if (_primitive && ctxt.isEnabled(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES)) {
161 ctxt.reportInputMismatch(this,
162 "Cannot map `null` into type %s (set DeserializationConfig.DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES to 'false' to allow)",
163 handledType().toString());
164 }
165 return _nullValue;
166 }
167
168 @Override
169 public Object getEmptyValue(DeserializationContext ctxt) throws JsonMappingException {
170 return _emptyValue;
171 }
172 }
173
174
179
180 @JacksonStdImpl
181 public final static class BooleanDeserializer
182 extends PrimitiveOrWrapperDeserializer<Boolean>
183 {
184 private static final long serialVersionUID = 1L;
185
186 final static BooleanDeserializer primitiveInstance = new BooleanDeserializer(Boolean.TYPE, Boolean.FALSE);
187 final static BooleanDeserializer wrapperInstance = new BooleanDeserializer(Boolean.class, null);
188
189 public BooleanDeserializer(Class<Boolean> cls, Boolean nvl)
190 {
191 super(cls, nvl, Boolean.FALSE);
192 }
193
194 @Override
195 public Boolean deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
196 {
197 JsonToken t = p.getCurrentToken();
198 if (t == JsonToken.VALUE_TRUE) {
199 return Boolean.TRUE;
200 }
201 if (t == JsonToken.VALUE_FALSE) {
202 return Boolean.FALSE;
203 }
204 return _parseBoolean(p, ctxt);
205 }
206
207
208
209 @Override
210 public Boolean deserializeWithType(JsonParser p, DeserializationContext ctxt,
211 TypeDeserializer typeDeserializer)
212 throws IOException
213 {
214 JsonToken t = p.getCurrentToken();
215 if (t == JsonToken.VALUE_TRUE) {
216 return Boolean.TRUE;
217 }
218 if (t == JsonToken.VALUE_FALSE) {
219 return Boolean.FALSE;
220 }
221 return _parseBoolean(p, ctxt);
222 }
223
224 protected final Boolean _parseBoolean(JsonParser p, DeserializationContext ctxt)
225 throws IOException
226 {
227 JsonToken t = p.getCurrentToken();
228 if (t == JsonToken.VALUE_NULL) {
229 return (Boolean) _coerceNullToken(ctxt, _primitive);
230 }
231 if (t == JsonToken.START_ARRAY) {
232 return _deserializeFromArray(p, ctxt);
233 }
234
235 if (t == JsonToken.VALUE_NUMBER_INT) {
236 return Boolean.valueOf(_parseBooleanFromInt(p, ctxt));
237 }
238
239 if (t == JsonToken.VALUE_STRING) {
240 String text = p.getText().trim();
241
242 if ("true".equals(text) || "True".equals(text)) {
243 _verifyStringForScalarCoercion(ctxt, text);
244 return Boolean.TRUE;
245 }
246 if ("false".equals(text) || "False".equals(text)) {
247 _verifyStringForScalarCoercion(ctxt, text);
248 return Boolean.FALSE;
249 }
250 if (text.length() == 0) {
251 return (Boolean) _coerceEmptyString(ctxt, _primitive);
252 }
253 if (_hasTextualNull(text)) {
254 return (Boolean) _coerceTextualNull(ctxt, _primitive);
255 }
256 return (Boolean) ctxt.handleWeirdStringValue(_valueClass, text,
257 "only \"true\" or \"false\" recognized");
258 }
259
260 if (t == JsonToken.VALUE_TRUE) {
261 return Boolean.TRUE;
262 }
263 if (t == JsonToken.VALUE_FALSE) {
264 return Boolean.FALSE;
265 }
266
267 return (Boolean) ctxt.handleUnexpectedToken(_valueClass, p);
268 }
269 }
270
271 @JacksonStdImpl
272 public static class ByteDeserializer
273 extends PrimitiveOrWrapperDeserializer<Byte>
274 {
275 private static final long serialVersionUID = 1L;
276
277 final static ByteDeserializer primitiveInstance = new ByteDeserializer(Byte.TYPE, (byte) 0);
278 final static ByteDeserializer wrapperInstance = new ByteDeserializer(Byte.class, null);
279
280 public ByteDeserializer(Class<Byte> cls, Byte nvl)
281 {
282 super(cls, nvl, (byte) 0);
283 }
284
285 @Override
286 public Byte deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
287 {
288 if (p.hasToken(JsonToken.VALUE_NUMBER_INT)) {
289 return p.getByteValue();
290 }
291 return _parseByte(p, ctxt);
292 }
293
294 protected Byte _parseByte(JsonParser p, DeserializationContext ctxt) throws IOException
295 {
296 JsonToken t = p.getCurrentToken();
297 if (t == JsonToken.VALUE_STRING) {
298 String text = p.getText().trim();
299 if (_hasTextualNull(text)) {
300 return (Byte) _coerceTextualNull(ctxt, _primitive);
301 }
302 int len = text.length();
303 if (len == 0) {
304 return (Byte) _coerceEmptyString(ctxt, _primitive);
305 }
306 _verifyStringForScalarCoercion(ctxt, text);
307 int value;
308 try {
309 value = NumberInput.parseInt(text);
310 } catch (IllegalArgumentException iae) {
311 return (Byte) ctxt.handleWeirdStringValue(_valueClass, text,
312 "not a valid Byte value");
313 }
314
315
316 if (_byteOverflow(value)) {
317 return (Byte) ctxt.handleWeirdStringValue(_valueClass, text,
318 "overflow, value cannot be represented as 8-bit value");
319
320 }
321 return Byte.valueOf((byte) value);
322 }
323 if (t == JsonToken.VALUE_NUMBER_FLOAT) {
324 if (!ctxt.isEnabled(DeserializationFeature.ACCEPT_FLOAT_AS_INT)) {
325 _failDoubleToIntCoercion(p, ctxt, "Byte");
326 }
327 return p.getByteValue();
328 }
329 if (t == JsonToken.VALUE_NULL) {
330 return (Byte) _coerceNullToken(ctxt, _primitive);
331 }
332
333 if (t == JsonToken.START_ARRAY) {
334 return _deserializeFromArray(p, ctxt);
335 }
336 if (t == JsonToken.VALUE_NUMBER_INT) {
337 return p.getByteValue();
338 }
339 return (Byte) ctxt.handleUnexpectedToken(_valueClass, p);
340 }
341 }
342
343 @JacksonStdImpl
344 public static class ShortDeserializer
345 extends PrimitiveOrWrapperDeserializer<Short>
346 {
347 private static final long serialVersionUID = 1L;
348
349 final static ShortDeserializer primitiveInstance = new ShortDeserializer(Short.TYPE, Short.valueOf((short)0));
350 final static ShortDeserializer wrapperInstance = new ShortDeserializer(Short.class, null);
351
352 public ShortDeserializer(Class<Short> cls, Short nvl)
353 {
354 super(cls, nvl, (short)0);
355 }
356
357 @Override
358 public Short deserialize(JsonParser p, DeserializationContext ctxt)
359 throws IOException
360 {
361 return _parseShort(p, ctxt);
362 }
363
364 protected Short _parseShort(JsonParser p, DeserializationContext ctxt) throws IOException
365 {
366 JsonToken t = p.getCurrentToken();
367 if (t == JsonToken.VALUE_NUMBER_INT) {
368 return p.getShortValue();
369 }
370 if (t == JsonToken.VALUE_STRING) {
371 String text = p.getText().trim();
372 int len = text.length();
373 if (len == 0) {
374 return (Short) _coerceEmptyString(ctxt, _primitive);
375 }
376 if (_hasTextualNull(text)) {
377 return (Short) _coerceTextualNull(ctxt, _primitive);
378 }
379 _verifyStringForScalarCoercion(ctxt, text);
380 int value;
381 try {
382 value = NumberInput.parseInt(text);
383 } catch (IllegalArgumentException iae) {
384 return (Short) ctxt.handleWeirdStringValue(_valueClass, text,
385 "not a valid Short value");
386 }
387
388 if (_shortOverflow(value)) {
389 return (Short) ctxt.handleWeirdStringValue(_valueClass, text,
390 "overflow, value cannot be represented as 16-bit value");
391 }
392 return Short.valueOf((short) value);
393 }
394 if (t == JsonToken.VALUE_NUMBER_FLOAT) {
395 if (!ctxt.isEnabled(DeserializationFeature.ACCEPT_FLOAT_AS_INT)) {
396 _failDoubleToIntCoercion(p, ctxt, "Short");
397 }
398 return p.getShortValue();
399 }
400 if (t == JsonToken.VALUE_NULL) {
401 return (Short) _coerceNullToken(ctxt, _primitive);
402 }
403 if (t == JsonToken.START_ARRAY) {
404 return _deserializeFromArray(p, ctxt);
405 }
406 return (Short) ctxt.handleUnexpectedToken(_valueClass, p);
407 }
408 }
409
410 @JacksonStdImpl
411 public static class CharacterDeserializer
412 extends PrimitiveOrWrapperDeserializer<Character>
413 {
414 private static final long serialVersionUID = 1L;
415
416 final static CharacterDeserializer primitiveInstance = new CharacterDeserializer(Character.TYPE, '\0');
417 final static CharacterDeserializer wrapperInstance = new CharacterDeserializer(Character.class, null);
418
419 public CharacterDeserializer(Class<Character> cls, Character nvl)
420 {
421 super(cls, nvl, '\0');
422 }
423
424 @Override
425 public Character deserialize(JsonParser p, DeserializationContext ctxt)
426 throws IOException
427 {
428 switch (p.getCurrentTokenId()) {
429 case JsonTokenId.ID_NUMBER_INT:
430 _verifyNumberForScalarCoercion(ctxt, p);
431 int value = p.getIntValue();
432 if (value >= 0 && value <= 0xFFFF) {
433 return Character.valueOf((char) value);
434 }
435 break;
436 case JsonTokenId.ID_STRING:
437
438 String text = p.getText();
439 if (text.length() == 1) {
440 return Character.valueOf(text.charAt(0));
441 }
442
443 if (text.length() == 0) {
444 return (Character) _coerceEmptyString(ctxt, _primitive);
445 }
446 break;
447 case JsonTokenId.ID_NULL:
448 return (Character) _coerceNullToken(ctxt, _primitive);
449 case JsonTokenId.ID_START_ARRAY:
450 return _deserializeFromArray(p, ctxt);
451 default:
452 }
453 return (Character) ctxt.handleUnexpectedToken(_valueClass, p);
454 }
455 }
456
457 @JacksonStdImpl
458 public final static class IntegerDeserializer
459 extends PrimitiveOrWrapperDeserializer<Integer>
460 {
461 private static final long serialVersionUID = 1L;
462
463 final static IntegerDeserializer primitiveInstance = new IntegerDeserializer(Integer.TYPE, 0);
464 final static IntegerDeserializer wrapperInstance = new IntegerDeserializer(Integer.class, null);
465
466 public IntegerDeserializer(Class<Integer> cls, Integer nvl) {
467 super(cls, nvl, 0);
468 }
469
470
471 @Override
472 public boolean isCachable() { return true; }
473
474 @Override
475 public Integer deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
476 if (p.hasToken(JsonToken.VALUE_NUMBER_INT)) {
477 return p.getIntValue();
478 }
479 return _parseInteger(p, ctxt);
480 }
481
482
483
484 @Override
485 public Integer deserializeWithType(JsonParser p, DeserializationContext ctxt,
486 TypeDeserializer typeDeserializer) throws IOException
487 {
488 if (p.hasToken(JsonToken.VALUE_NUMBER_INT)) {
489 return p.getIntValue();
490 }
491 return _parseInteger(p, ctxt);
492 }
493
494 protected final Integer _parseInteger(JsonParser p, DeserializationContext ctxt) throws IOException
495 {
496 switch (p.getCurrentTokenId()) {
497
498 case JsonTokenId.ID_NUMBER_INT:
499 return Integer.valueOf(p.getIntValue());
500 case JsonTokenId.ID_NUMBER_FLOAT:
501 if (!ctxt.isEnabled(DeserializationFeature.ACCEPT_FLOAT_AS_INT)) {
502 _failDoubleToIntCoercion(p, ctxt, "Integer");
503 }
504 return Integer.valueOf(p.getValueAsInt());
505 case JsonTokenId.ID_STRING:
506 String text = p.getText().trim();
507 int len = text.length();
508 if (len == 0) {
509 return (Integer) _coerceEmptyString(ctxt, _primitive);
510 }
511 if (_hasTextualNull(text)) {
512 return (Integer) _coerceTextualNull(ctxt, _primitive);
513 }
514 _verifyStringForScalarCoercion(ctxt, text);
515 try {
516 if (len > 9) {
517 long l = Long.parseLong(text);
518 if (_intOverflow(l)) {
519 return (Integer) ctxt.handleWeirdStringValue(_valueClass, text, String.format(
520 "Overflow: numeric value (%s) out of range of Integer (%d - %d)",
521 text, Integer.MIN_VALUE, Integer.MAX_VALUE));
522 }
523 return Integer.valueOf((int) l);
524 }
525 return Integer.valueOf(NumberInput.parseInt(text));
526 } catch (IllegalArgumentException iae) {
527 return (Integer) ctxt.handleWeirdStringValue(_valueClass, text,
528 "not a valid Integer value");
529 }
530 case JsonTokenId.ID_NULL:
531 return (Integer) _coerceNullToken(ctxt, _primitive);
532 case JsonTokenId.ID_START_ARRAY:
533 return _deserializeFromArray(p, ctxt);
534 }
535
536 return (Integer) ctxt.handleUnexpectedToken(_valueClass, p);
537 }
538 }
539
540 @JacksonStdImpl
541 public final static class LongDeserializer
542 extends PrimitiveOrWrapperDeserializer<Long>
543 {
544 private static final long serialVersionUID = 1L;
545
546 final static LongDeserializer primitiveInstance = new LongDeserializer(Long.TYPE, 0L);
547 final static LongDeserializer wrapperInstance = new LongDeserializer(Long.class, null);
548
549 public LongDeserializer(Class<Long> cls, Long nvl) {
550 super(cls, nvl, 0L);
551 }
552
553
554 @Override
555 public boolean isCachable() { return true; }
556
557 @Override
558 public Long deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
559 if (p.hasToken(JsonToken.VALUE_NUMBER_INT)) {
560 return p.getLongValue();
561 }
562 return _parseLong(p, ctxt);
563 }
564
565 protected final Long _parseLong(JsonParser p, DeserializationContext ctxt) throws IOException
566 {
567 switch (p.getCurrentTokenId()) {
568
569 case JsonTokenId.ID_NUMBER_INT:
570 return p.getLongValue();
571 case JsonTokenId.ID_NUMBER_FLOAT:
572 if (!ctxt.isEnabled(DeserializationFeature.ACCEPT_FLOAT_AS_INT)) {
573 _failDoubleToIntCoercion(p, ctxt, "Long");
574 }
575 return p.getValueAsLong();
576 case JsonTokenId.ID_STRING:
577 String text = p.getText().trim();
578 if (text.length() == 0) {
579 return (Long) _coerceEmptyString(ctxt, _primitive);
580 }
581 if (_hasTextualNull(text)) {
582 return (Long) _coerceTextualNull(ctxt, _primitive);
583 }
584 _verifyStringForScalarCoercion(ctxt, text);
585
586 try {
587 return Long.valueOf(NumberInput.parseLong(text));
588 } catch (IllegalArgumentException iae) { }
589 return (Long) ctxt.handleWeirdStringValue(_valueClass, text,
590 "not a valid Long value");
591
592 case JsonTokenId.ID_NULL:
593 return (Long) _coerceNullToken(ctxt, _primitive);
594 case JsonTokenId.ID_START_ARRAY:
595 return _deserializeFromArray(p, ctxt);
596 }
597
598 return (Long) ctxt.handleUnexpectedToken(_valueClass, p);
599 }
600 }
601
602 @JacksonStdImpl
603 public static class FloatDeserializer
604 extends PrimitiveOrWrapperDeserializer<Float>
605 {
606 private static final long serialVersionUID = 1L;
607
608 final static FloatDeserializer primitiveInstance = new FloatDeserializer(Float.TYPE, 0.f);
609 final static FloatDeserializer wrapperInstance = new FloatDeserializer(Float.class, null);
610
611 public FloatDeserializer(Class<Float> cls, Float nvl) {
612 super(cls, nvl, 0.f);
613 }
614
615 @Override
616 public Float deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
617 {
618 return _parseFloat(p, ctxt);
619 }
620
621 protected final Float _parseFloat(JsonParser p, DeserializationContext ctxt)
622 throws IOException
623 {
624
625 JsonToken t = p.getCurrentToken();
626
627 if (t == JsonToken.VALUE_NUMBER_FLOAT || t == JsonToken.VALUE_NUMBER_INT) {
628 return p.getFloatValue();
629 }
630
631 if (t == JsonToken.VALUE_STRING) {
632 String text = p.getText().trim();
633 if ((text.length() == 0)) {
634 return (Float) _coerceEmptyString(ctxt, _primitive);
635 }
636 if (_hasTextualNull(text)) {
637 return (Float) _coerceTextualNull(ctxt, _primitive);
638 }
639 switch (text.charAt(0)) {
640 case 'I':
641 if (_isPosInf(text)) {
642 return Float.POSITIVE_INFINITY;
643 }
644 break;
645 case 'N':
646 if (_isNaN(text)) {
647 return Float.NaN;
648 }
649 break;
650 case '-':
651 if (_isNegInf(text)) {
652 return Float.NEGATIVE_INFINITY;
653 }
654 break;
655 }
656 _verifyStringForScalarCoercion(ctxt, text);
657 try {
658 return Float.parseFloat(text);
659 } catch (IllegalArgumentException iae) { }
660 return (Float) ctxt.handleWeirdStringValue(_valueClass, text,
661 "not a valid Float value");
662 }
663 if (t == JsonToken.VALUE_NULL) {
664 return (Float) _coerceNullToken(ctxt, _primitive);
665 }
666 if (t == JsonToken.START_ARRAY) {
667 return _deserializeFromArray(p, ctxt);
668 }
669
670 return (Float) ctxt.handleUnexpectedToken(_valueClass, p);
671 }
672 }
673
674 @JacksonStdImpl
675 public static class DoubleDeserializer
676 extends PrimitiveOrWrapperDeserializer<Double>
677 {
678 private static final long serialVersionUID = 1L;
679
680 final static DoubleDeserializer primitiveInstance = new DoubleDeserializer(Double.TYPE, 0.d);
681 final static DoubleDeserializer wrapperInstance = new DoubleDeserializer(Double.class, null);
682
683 public DoubleDeserializer(Class<Double> cls, Double nvl) {
684 super(cls, nvl, 0.d);
685 }
686
687 @Override
688 public Double deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
689 return _parseDouble(p, ctxt);
690 }
691
692
693
694 @Override
695 public Double deserializeWithType(JsonParser p, DeserializationContext ctxt,
696 TypeDeserializer typeDeserializer) throws IOException
697 {
698 return _parseDouble(p, ctxt);
699 }
700
701 protected final Double _parseDouble(JsonParser p, DeserializationContext ctxt) throws IOException
702 {
703 JsonToken t = p.getCurrentToken();
704 if (t == JsonToken.VALUE_NUMBER_INT || t == JsonToken.VALUE_NUMBER_FLOAT) {
705 return p.getDoubleValue();
706 }
707 if (t == JsonToken.VALUE_STRING) {
708 String text = p.getText().trim();
709 if ((text.length() == 0)) {
710 return (Double) _coerceEmptyString(ctxt, _primitive);
711 }
712 if (_hasTextualNull(text)) {
713 return (Double) _coerceTextualNull(ctxt, _primitive);
714 }
715 switch (text.charAt(0)) {
716 case 'I':
717 if (_isPosInf(text)) {
718 return Double.POSITIVE_INFINITY;
719 }
720 break;
721 case 'N':
722 if (_isNaN(text)) {
723 return Double.NaN;
724 }
725 break;
726 case '-':
727 if (_isNegInf(text)) {
728 return Double.NEGATIVE_INFINITY;
729 }
730 break;
731 }
732 _verifyStringForScalarCoercion(ctxt, text);
733 try {
734 return parseDouble(text);
735 } catch (IllegalArgumentException iae) { }
736 return (Double) ctxt.handleWeirdStringValue(_valueClass, text,
737 "not a valid Double value");
738 }
739 if (t == JsonToken.VALUE_NULL) {
740 return (Double) _coerceNullToken(ctxt, _primitive);
741 }
742 if (t == JsonToken.START_ARRAY) {
743 return _deserializeFromArray(p, ctxt);
744 }
745
746 return (Double) ctxt.handleUnexpectedToken(_valueClass, p);
747 }
748 }
749
750
760 @SuppressWarnings("serial")
761 @JacksonStdImpl
762 public static class NumberDeserializer
763 extends StdScalarDeserializer<Object>
764 {
765 public final static NumberDeserializer instance = new NumberDeserializer();
766
767 public NumberDeserializer() {
768 super(Number.class);
769 }
770
771 @Override
772 public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
773 {
774 switch (p.getCurrentTokenId()) {
775 case JsonTokenId.ID_NUMBER_INT:
776 if (ctxt.hasSomeOfFeatures(F_MASK_INT_COERCIONS)) {
777 return _coerceIntegral(p, ctxt);
778 }
779 return p.getNumberValue();
780
781 case JsonTokenId.ID_NUMBER_FLOAT:
782 if (ctxt.isEnabled(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)) {
783
784 if (!p.isNaN()) {
785 return p.getDecimalValue();
786 }
787 }
788 return p.getNumberValue();
789
790 case JsonTokenId.ID_STRING:
791
794 String text = p.getText().trim();
795 if ((text.length() == 0)) {
796
797 return getNullValue(ctxt);
798 }
799 if (_hasTextualNull(text)) {
800
801 return getNullValue(ctxt);
802 }
803 if (_isPosInf(text)) {
804 return Double.POSITIVE_INFINITY;
805 }
806 if (_isNegInf(text)) {
807 return Double.NEGATIVE_INFINITY;
808 }
809 if (_isNaN(text)) {
810 return Double.NaN;
811 }
812 _verifyStringForScalarCoercion(ctxt, text);
813 try {
814 if (!_isIntNumber(text)) {
815 if (ctxt.isEnabled(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)) {
816 return new BigDecimal(text);
817 }
818 return Double.valueOf(text);
819 }
820 if (ctxt.isEnabled(DeserializationFeature.USE_BIG_INTEGER_FOR_INTS)) {
821 return new BigInteger(text);
822 }
823 long value = Long.parseLong(text);
824 if (!ctxt.isEnabled(DeserializationFeature.USE_LONG_FOR_INTS)) {
825 if (value <= Integer.MAX_VALUE && value >= Integer.MIN_VALUE) {
826 return Integer.valueOf((int) value);
827 }
828 }
829 return Long.valueOf(value);
830 } catch (IllegalArgumentException iae) {
831 return ctxt.handleWeirdStringValue(_valueClass, text,
832 "not a valid number");
833 }
834 case JsonTokenId.ID_START_ARRAY:
835 return _deserializeFromArray(p, ctxt);
836 }
837
838 return ctxt.handleUnexpectedToken(_valueClass, p);
839 }
840
841
847 @Override
848 public Object deserializeWithType(JsonParser p, DeserializationContext ctxt,
849 TypeDeserializer typeDeserializer)
850 throws IOException
851 {
852 switch (p.getCurrentTokenId()) {
853 case JsonTokenId.ID_NUMBER_INT:
854 case JsonTokenId.ID_NUMBER_FLOAT:
855 case JsonTokenId.ID_STRING:
856
857 return deserialize(p, ctxt);
858 }
859 return typeDeserializer.deserializeTypedFromScalar(p, ctxt);
860 }
861 }
862
863
869
870
874 @SuppressWarnings("serial")
875 @JacksonStdImpl
876 public static class BigIntegerDeserializer
877 extends StdScalarDeserializer<BigInteger>
878 {
879 public final static BigIntegerDeserializer instance = new BigIntegerDeserializer();
880
881 public BigIntegerDeserializer() { super(BigInteger.class); }
882
883 @Override
884 public Object getEmptyValue(DeserializationContext ctxt) {
885 return BigInteger.ZERO;
886 }
887
888 @SuppressWarnings("incomplete-switch")
889 @Override
890 public BigInteger deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
891 {
892 switch (p.getCurrentTokenId()) {
893 case JsonTokenId.ID_NUMBER_INT:
894 switch (p.getNumberType()) {
895 case INT:
896 case LONG:
897 case BIG_INTEGER:
898 return p.getBigIntegerValue();
899 }
900 break;
901 case JsonTokenId.ID_NUMBER_FLOAT:
902 if (!ctxt.isEnabled(DeserializationFeature.ACCEPT_FLOAT_AS_INT)) {
903 _failDoubleToIntCoercion(p, ctxt, "java.math.BigInteger");
904 }
905 return p.getDecimalValue().toBigInteger();
906 case JsonTokenId.ID_START_ARRAY:
907 return _deserializeFromArray(p, ctxt);
908 case JsonTokenId.ID_STRING:
909 String text = p.getText().trim();
910
911 if (_isEmptyOrTextualNull(text)) {
912 _verifyNullForScalarCoercion(ctxt, text);
913 return getNullValue(ctxt);
914 }
915 _verifyStringForScalarCoercion(ctxt, text);
916 try {
917 return new BigInteger(text);
918 } catch (IllegalArgumentException iae) { }
919 return (BigInteger) ctxt.handleWeirdStringValue(_valueClass, text,
920 "not a valid representation");
921 }
922
923 return (BigInteger) ctxt.handleUnexpectedToken(_valueClass, p);
924 }
925 }
926
927 @SuppressWarnings("serial")
928 @JacksonStdImpl
929 public static class BigDecimalDeserializer
930 extends StdScalarDeserializer<BigDecimal>
931 {
932 public final static BigDecimalDeserializer instance = new BigDecimalDeserializer();
933
934 public BigDecimalDeserializer() { super(BigDecimal.class); }
935
936 @Override
937 public Object getEmptyValue(DeserializationContext ctxt) {
938 return BigDecimal.ZERO;
939 }
940
941 @Override
942 public BigDecimal deserialize(JsonParser p, DeserializationContext ctxt)
943 throws IOException
944 {
945 switch (p.getCurrentTokenId()) {
946 case JsonTokenId.ID_NUMBER_INT:
947 case JsonTokenId.ID_NUMBER_FLOAT:
948 return p.getDecimalValue();
949 case JsonTokenId.ID_STRING:
950 String text = p.getText().trim();
951
952 if (_isEmptyOrTextualNull(text)) {
953 _verifyNullForScalarCoercion(ctxt, text);
954 return getNullValue(ctxt);
955 }
956 _verifyStringForScalarCoercion(ctxt, text);
957 try {
958 return new BigDecimal(text);
959 } catch (IllegalArgumentException iae) { }
960 return (BigDecimal) ctxt.handleWeirdStringValue(_valueClass, text,
961 "not a valid representation");
962 case JsonTokenId.ID_START_ARRAY:
963 return _deserializeFromArray(p, ctxt);
964 }
965
966 return (BigDecimal) ctxt.handleUnexpectedToken(_valueClass, p);
967 }
968 }
969 }
970