Jackson Data Binding Source Code

Jackson is "the Java JSON library" or "the best JSON parser for Java". Or simply as "JSON for Java".

  • Jackson Data Binding module allows you to converts JSON to and from POJO (Plain Old Java Object) using property accessor or using annotations.
  • Jackson Databind Source Code files are provided in the source packge (jackson-databind-2.12.4-sources.jar). You can download it at Jackson Maven Website.

    You can also browse Jackson Databind Source Code below:

    ✍: FYIcenter.com

    com/fasterxml/jackson/databind/deser/std/NumberDeserializers.java

    package com.fasterxml.jackson.databind.deser.std;
    
    import java.io.IOException;
    import java.math.BigDecimal;
    import java.math.BigInteger;
    import java.util.HashSet;
    
    import com.fasterxml.jackson.core.*;
    import com.fasterxml.jackson.core.io.NumberInput;
    import com.fasterxml.jackson.databind.*;
    import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
    import com.fasterxml.jackson.databind.cfg.CoercionAction;
    import com.fasterxml.jackson.databind.cfg.CoercionInputShape;
    import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
    import com.fasterxml.jackson.databind.type.LogicalType;
    import com.fasterxml.jackson.databind.util.AccessPattern;
    import com.fasterxml.jackson.databind.util.ClassUtil;
    
    /**
     * Container class for deserializers that handle core JDK primitive
     * (and matching wrapper) types, as well as standard "big" numeric types.
     * Note that this includes types such as {@link java.lang.Boolean}
     * and {@link java.lang.Character} which are not strictly numeric,
     * but are part of primitive/wrapper types.
     */
    public class NumberDeserializers
    {
        private final static HashSet<String> _classNames = new HashSet<String>();
        static {
            // note: can skip primitive types; other ways to check them:
            Class<?>[] numberTypes = new Class<?>[] {
                Boolean.class,
                Byte.class,
                Short.class,
                Character.class,
                Integer.class,
                Long.class,
                Float.class,
                Double.class,
                // and more generic ones
                Number.class, BigDecimal.class, BigInteger.class
            };
            for (Class<?> cls : numberTypes) {
                _classNames.add(cls.getName());
            }
        }
    
        public static JsonDeserializer<?> find(Class<?> rawType, String clsName) {
            if (rawType.isPrimitive()) {
                if (rawType == Integer.TYPE) {
                    return IntegerDeserializer.primitiveInstance;
                }
                if (rawType == Boolean.TYPE) {
                    return BooleanDeserializer.primitiveInstance;
                }
                if (rawType == Long.TYPE) {
                    return LongDeserializer.primitiveInstance;
                }
                if (rawType == Double.TYPE) {
                    return DoubleDeserializer.primitiveInstance;
                }
                if (rawType == Character.TYPE) {
                    return CharacterDeserializer.primitiveInstance;
                }
                if (rawType == Byte.TYPE) {
                    return ByteDeserializer.primitiveInstance;
                }
                if (rawType == Short.TYPE) {
                    return ShortDeserializer.primitiveInstance;
                }
                if (rawType == Float.TYPE) {
                    return FloatDeserializer.primitiveInstance;
                }
                // [databind#2679]: bit odd place for this (Void.class handled in
                // `JdkDeserializers`), due to `void` being primitive type
                if (rawType == Void.TYPE) {
                    return NullifyingDeserializer.instance;
                }
            } else if (_classNames.contains(clsName)) {
                // Start with most common types; int, boolean, long, double
                if (rawType == Integer.class) {
                    return IntegerDeserializer.wrapperInstance;
                }
                if (rawType == Boolean.class) {
                    return BooleanDeserializer.wrapperInstance;
                }
                if (rawType == Long.class) {
                    return LongDeserializer.wrapperInstance;
                }
                if (rawType == Double.class) {
                    return DoubleDeserializer.wrapperInstance;
                }
                if (rawType == Character.class) {
                    return CharacterDeserializer.wrapperInstance;
                }
                if (rawType == Byte.class) {
                    return ByteDeserializer.wrapperInstance;
                }
                if (rawType == Short.class) {
                    return ShortDeserializer.wrapperInstance;
                }
                if (rawType == Float.class) {
                    return FloatDeserializer.wrapperInstance;
                }
                if (rawType == Number.class) {
                    return NumberDeserializer.instance;
                }
                if (rawType == BigDecimal.class) {
                    return BigDecimalDeserializer.instance;
                }
                if (rawType == BigInteger.class) {
                    return BigIntegerDeserializer.instance;
                }
            } else {
                return null;
            }
            // should never occur
            throw new IllegalArgumentException("Internal error: can't find deserializer for "+rawType.getName());
        }
    
        /*
        /**********************************************************
        /* Then one intermediate base class for things that have
        /* both primitive and wrapper types
        /**********************************************************
         */
    
        protected abstract static class PrimitiveOrWrapperDeserializer<T>
            extends StdScalarDeserializer<T>
        {
            private static final long serialVersionUID = 1L;
    
            // @since 2.12
            protected final LogicalType _logicalType;
    
            protected final T _nullValue;
    
            // @since 2.9
            protected final T _emptyValue;
    
            protected final boolean _primitive;
    
            // @since 2.12
            protected PrimitiveOrWrapperDeserializer(Class<T> vc, LogicalType logicalType,
                    T nvl, T empty) {
                super(vc);
                _logicalType = logicalType;
                _nullValue = nvl;
                _emptyValue = empty;
                _primitive = vc.isPrimitive();
            }
    
            @Deprecated // since 2.12
            protected PrimitiveOrWrapperDeserializer(Class<T> vc, T nvl, T empty) {
                this(vc, LogicalType.OtherScalar, nvl, empty);
            }
    
            @Override
            public AccessPattern getNullAccessPattern() {
                // 02-Feb-2017, tatu: For primitives we must dynamically check (and possibly throw
                //     exception); for wrappers not.
                if (_primitive) {
                    return AccessPattern.DYNAMIC;
                }
                if (_nullValue == null) {
                    return AccessPattern.ALWAYS_NULL;
                }
                return AccessPattern.CONSTANT;
            }
    
            @Override
            public final T getNullValue(DeserializationContext ctxt) throws JsonMappingException {
                // 01-Mar-2017, tatu: Alas, not all paths lead to `_coerceNull()`, as `SettableBeanProperty`
                //    short-circuits `null` handling. Hence need this check as well.
                if (_primitive && ctxt.isEnabled(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES)) {
                    ctxt.reportInputMismatch(this,
                            "Cannot map `null` into type %s (set DeserializationConfig.DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES to 'false' to allow)",
                            ClassUtil.classNameOf(handledType()));
                }
                return _nullValue;
            }
    
            @Override
            public Object getEmptyValue(DeserializationContext ctxt) throws JsonMappingException {
                return _emptyValue;
            }
    
            @Override // since 2.12
            public final LogicalType logicalType() {
                return _logicalType;
            }
        }
    
        /*
        /**********************************************************
        /* Then primitive/wrapper types
        /**********************************************************
         */
    
        @JacksonStdImpl
        public final static class BooleanDeserializer
            extends PrimitiveOrWrapperDeserializer<Boolean>
        {
            private static final long serialVersionUID = 1L;
    
            final static BooleanDeserializer primitiveInstance = new BooleanDeserializer(Boolean.TYPE, Boolean.FALSE);
            final static BooleanDeserializer wrapperInstance = new BooleanDeserializer(Boolean.class, null);
    
            public BooleanDeserializer(Class<Boolean> cls, Boolean nvl)
            {
                super(cls, LogicalType.Boolean, nvl, Boolean.FALSE);
            }
    
            @Override
            public Boolean deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
            {
                JsonToken t = p.currentToken();
                if (t == JsonToken.VALUE_TRUE) {
                    return Boolean.TRUE;
                }
                if (t == JsonToken.VALUE_FALSE) {
                    return Boolean.FALSE;
                }
                if (_primitive) {
                    return _parseBooleanPrimitive(p, ctxt);
                }
                return _parseBoolean(p, ctxt, _valueClass);
            }
    
            // Since we can never have type info ("natural type"; String, Boolean, Integer, Double):
            // (is it an error to even call this version?)
            @Override
            public Boolean deserializeWithType(JsonParser p, DeserializationContext ctxt,
                    TypeDeserializer typeDeserializer)
                throws IOException
            {
                JsonToken t = p.currentToken();
                if (t == JsonToken.VALUE_TRUE) {
                    return Boolean.TRUE;
                }
                if (t == JsonToken.VALUE_FALSE) {
                    return Boolean.FALSE;
                }
                if (_primitive) {
                    return _parseBooleanPrimitive(p, ctxt);
                }
                return _parseBoolean(p, ctxt, _valueClass);
            }
        }
    
        @JacksonStdImpl
        public static class ByteDeserializer
            extends PrimitiveOrWrapperDeserializer<Byte>
        {
            private static final long serialVersionUID = 1L;
    
            final static ByteDeserializer primitiveInstance = new ByteDeserializer(Byte.TYPE, (byte) 0);
            final static ByteDeserializer wrapperInstance = new ByteDeserializer(Byte.class, null);
    
            public ByteDeserializer(Class<Byte> cls, Byte nvl)
            {
                super(cls, LogicalType.Integer, nvl, (byte) 0);
            }
    
            @Override
            public Byte deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
            {
                if (p.isExpectedNumberIntToken()) {
                    return p.getByteValue();
                }
                if (_primitive) {
                    return _parseBytePrimitive(p, ctxt);
                }
                return _parseByte(p, ctxt);
            }
    
            protected Byte _parseByte(JsonParser p, DeserializationContext ctxt)
                    throws IOException
            {
                String text;
    
                switch (p.currentTokenId()) {
                case JsonTokenId.ID_STRING: // let's do implicit re-parse
                    text = p.getText();
                    break;
                case JsonTokenId.ID_NUMBER_FLOAT:
                    final CoercionAction act = _checkFloatToIntCoercion(p, ctxt, _valueClass);
                    if (act == CoercionAction.AsNull) {
                        return (Byte) getNullValue(ctxt);
                    }
                    if (act == CoercionAction.AsEmpty) {
                        return (Byte) getEmptyValue(ctxt);
                    }
                    return p.getByteValue();
                case JsonTokenId.ID_NULL: // null fine for non-primitive
                    return (Byte) getNullValue(ctxt);
                case JsonTokenId.ID_NUMBER_INT:
                    return p.getByteValue();
                case JsonTokenId.ID_START_ARRAY:
                    return (Byte) _deserializeFromArray(p, ctxt);
                // 29-Jun-2020, tatu: New! "Scalar from Object" (mostly for XML)
                case JsonTokenId.ID_START_OBJECT:
                    text = ctxt.extractScalarFromObject(p, this, _valueClass);
                    break;
                default:
                    return (Byte) ctxt.handleUnexpectedToken(getValueType(ctxt), p);
                }
    
                // Rest of the processing is for coercion from String
                final CoercionAction act = _checkFromStringCoercion(ctxt, text);
                if (act == CoercionAction.AsNull) {
                    return (Byte) getNullValue(ctxt);
                }
                if (act == CoercionAction.AsEmpty) {
                    return (Byte) getEmptyValue(ctxt);
                }
                text = text.trim();
                if (_checkTextualNull(ctxt, text)) {
                    return (Byte) getNullValue(ctxt);
                }
                int value;
                try {
                    value = NumberInput.parseInt(text);
                } catch (IllegalArgumentException iae) {
                    return (Byte) ctxt.handleWeirdStringValue(_valueClass, text,
                            "not a valid Byte value");
                }
                // So far so good: but does it fit?
                // as per [JACKSON-804], allow range up to 255, inclusive
                if (_byteOverflow(value)) {
                    return (Byte) ctxt.handleWeirdStringValue(_valueClass, text,
                            "overflow, value cannot be represented as 8-bit value");
                    // fall-through for deferred fails
                }
                return Byte.valueOf((byte) value);
            }
        }
    
        @JacksonStdImpl
        public static class ShortDeserializer
            extends PrimitiveOrWrapperDeserializer<Short>
        {
            private static final long serialVersionUID = 1L;
    
            final static ShortDeserializer primitiveInstance = new ShortDeserializer(Short.TYPE, Short.valueOf((short)0));
            final static ShortDeserializer wrapperInstance = new ShortDeserializer(Short.class, null);
            
            public ShortDeserializer(Class<Short> cls, Short nvl)
            {
                super(cls, LogicalType.Integer, nvl, (short)0);
            }
    
            @Override
            public Short deserialize(JsonParser p, DeserializationContext ctxt)
                throws IOException
            {
                if (p.isExpectedNumberIntToken()) {
                    return p.getShortValue();
                }
                if (_primitive) {
                    return _parseShortPrimitive(p, ctxt);
                }
                return _parseShort(p, ctxt);
            }
    
            protected Short _parseShort(JsonParser p, DeserializationContext ctxt)
                    throws IOException
            {
                String text;
                switch (p.currentTokenId()) {
                case JsonTokenId.ID_STRING: // let's do implicit re-parse
                    text = p.getText();
                    break;
                case JsonTokenId.ID_NUMBER_FLOAT:
                    final CoercionAction act = _checkFloatToIntCoercion(p, ctxt, _valueClass);
                    if (act == CoercionAction.AsNull) {
                        return (Short) getNullValue(ctxt);
                    }
                    if (act == CoercionAction.AsEmpty) {
                        return (Short) getEmptyValue(ctxt);
                    }
                    return p.getShortValue();
                case JsonTokenId.ID_NULL: // null fine for non-primitive
                    return (Short) getNullValue(ctxt);
                case JsonTokenId.ID_NUMBER_INT:
                    return p.getShortValue();
                // 29-Jun-2020, tatu: New! "Scalar from Object" (mostly for XML)
                case JsonTokenId.ID_START_OBJECT:
                    text = ctxt.extractScalarFromObject(p, this, _valueClass);
                    break;
                case JsonTokenId.ID_START_ARRAY:
                    return (Short)_deserializeFromArray(p, ctxt);
                default:
                    return (Short) ctxt.handleUnexpectedToken(getValueType(ctxt), p);
                }
    
                // Rest of the processing is for coercion from String
                final CoercionAction act = _checkFromStringCoercion(ctxt, text);
                if (act == CoercionAction.AsNull) {
                    return (Short) getNullValue(ctxt);
                }
                if (act == CoercionAction.AsEmpty) {
                    return (Short) getEmptyValue(ctxt);
                }
                text = text.trim();
                if (_checkTextualNull(ctxt, text)) {
                    return (Short) getNullValue(ctxt);
                }
                int value;
                try {
                    value = NumberInput.parseInt(text);
                } catch (IllegalArgumentException iae) {
                    return (Short) ctxt.handleWeirdStringValue(_valueClass, text,
                            "not a valid Short value");
                }
                // So far so good: but does it fit?
                if (_shortOverflow(value)) {
                    return (Short) ctxt.handleWeirdStringValue(_valueClass, text,
                            "overflow, value cannot be represented as 16-bit value");
                }
                return (short) value;
            }
        }
    
        @JacksonStdImpl
        public static class CharacterDeserializer
            extends PrimitiveOrWrapperDeserializer<Character>
        {
            private static final long serialVersionUID = 1L;
    
            final static CharacterDeserializer primitiveInstance = new CharacterDeserializer(Character.TYPE, '\0');
            final static CharacterDeserializer wrapperInstance = new CharacterDeserializer(Character.class, null);
            
            public CharacterDeserializer(Class<Character> cls, Character nvl)
            {
                super(cls,
                        // 07-Jun-2020, tatu: Debatable if it should be "OtherScalar" or Integer but...
                        LogicalType.Integer, nvl, '\0');
            }
    
            @Override
            public Character deserialize(JsonParser p, DeserializationContext ctxt)
                throws IOException
            {
                String text;
                switch (p.currentTokenId()) {
                case JsonTokenId.ID_STRING:
                    // 23-Jun-2020, tatu: Unlike real numeric types, Character/char does not
                    //   have canonical shape in JSON, and String in particular does not need
                    //   coercion -- as long as it has length of 1.
                    text = p.getText();
                    break;
                case JsonTokenId.ID_NUMBER_INT: // ok iff Unicode value
                    CoercionAction act = ctxt.findCoercionAction(logicalType(), _valueClass, CoercionInputShape.Integer);
                    switch (act) {
                    case Fail:
                        _checkCoercionFail(ctxt, act, _valueClass, p.getNumberValue(),
                                "Integer value ("+p.getText()+")");
                        // fall-through in unlikely case of returning
                    case AsNull:
                        return getNullValue(ctxt);
                    case AsEmpty:
                        return (Character) getEmptyValue(ctxt);
                    default:
                    }
                    int value = p.getIntValue();
                    if (value >= 0 && value <= 0xFFFF) {
                        return Character.valueOf((char) value);
                    }
                    return (Character) ctxt.handleWeirdNumberValue(handledType(), value,
                            "value outside valid Character range (0x0000 - 0xFFFF)");
                case JsonTokenId.ID_NULL:
                    if (_primitive) {
                        _verifyNullForPrimitive(ctxt);
                    }
                    return (Character) getNullValue(ctxt);
                // 29-Jun-2020, tatu: New! "Scalar from Object" (mostly for XML)
                case JsonTokenId.ID_START_OBJECT:
                    text = ctxt.extractScalarFromObject(p, this, _valueClass);
                    break;
                case JsonTokenId.ID_START_ARRAY:
                    return _deserializeFromArray(p, ctxt);
                default:
                    return (Character) ctxt.handleUnexpectedToken(getValueType(ctxt), p);
                }
    
                if (text.length() == 1) {
                    return Character.valueOf(text.charAt(0));
                }
                CoercionAction act = _checkFromStringCoercion(ctxt, text);
                if (act == CoercionAction.AsNull) {
                    return getNullValue(ctxt);
                }
                if (act == CoercionAction.AsEmpty) {
                    return (Character) getEmptyValue(ctxt);
                }
                text = text.trim();
                if (_checkTextualNull(ctxt, text)) {
                    return (Character) getNullValue(ctxt);
                }
                return (Character) ctxt.handleWeirdStringValue(handledType(), text,
                        "Expected either Integer value code or 1-character String");
            }
        }
    
        @JacksonStdImpl
        public final static class IntegerDeserializer
            extends PrimitiveOrWrapperDeserializer<Integer>
        {
            private static final long serialVersionUID = 1L;
    
            final static IntegerDeserializer primitiveInstance = new IntegerDeserializer(Integer.TYPE, 0);
            final static IntegerDeserializer wrapperInstance = new IntegerDeserializer(Integer.class, null);
            
            public IntegerDeserializer(Class<Integer> cls, Integer nvl) {
                super(cls, LogicalType.Integer, nvl, 0);
            }
    
            // since 2.6, slightly faster lookups for this very common type
            @Override
            public boolean isCachable() { return true; }
    
            @Override
            public Integer deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
                if (p.isExpectedNumberIntToken()) {
                    return p.getIntValue();
                }
                if (_primitive) {
                    return _parseIntPrimitive(p, ctxt);
                }
                return _parseInteger(p, ctxt, Integer.class);
            }
    
            // Since we can never have type info ("natural type"; String, Boolean, Integer, Double):
            // (is it an error to even call this version?)
            @Override
            public Integer deserializeWithType(JsonParser p, DeserializationContext ctxt,
                    TypeDeserializer typeDeserializer) throws IOException
            {
                if (p.isExpectedNumberIntToken()) {
                    return p.getIntValue();
                }
                if (_primitive) {
                    return _parseIntPrimitive(p, ctxt);
                }
                return _parseInteger(p, ctxt, Integer.class);
            }
        }
    
        @JacksonStdImpl
        public final static class LongDeserializer
            extends PrimitiveOrWrapperDeserializer<Long>
        {
            private static final long serialVersionUID = 1L;
    
            final static LongDeserializer primitiveInstance = new LongDeserializer(Long.TYPE, 0L);
            final static LongDeserializer wrapperInstance = new LongDeserializer(Long.class, null);
            
            public LongDeserializer(Class<Long> cls, Long nvl) {
                super(cls, LogicalType.Integer, nvl, 0L);
            }
    
            // since 2.6, slightly faster lookups for this very common type
            @Override
            public boolean isCachable() { return true; }
            
            @Override
            public Long deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
                if (p.isExpectedNumberIntToken()) {
                    return p.getLongValue();
                }
                if (_primitive) {
                    return _parseLongPrimitive(p, ctxt);
                }
                return _parseLong(p, ctxt, Long.class);
            }
        }
    
        @JacksonStdImpl
        public static class FloatDeserializer
            extends PrimitiveOrWrapperDeserializer<Float>
        {
            private static final long serialVersionUID = 1L;
    
            final static FloatDeserializer primitiveInstance = new FloatDeserializer(Float.TYPE, 0.f);
            final static FloatDeserializer wrapperInstance = new FloatDeserializer(Float.class, null);
            
            public FloatDeserializer(Class<Float> cls, Float nvl) {
                super(cls, LogicalType.Float, nvl, 0.f);
            }
    
            @Override
            public Float deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
            {
                if (p.hasToken(JsonToken.VALUE_NUMBER_FLOAT)) {
                    return p.getFloatValue();
                }
                if (_primitive) {
                    return _parseFloatPrimitive(p, ctxt);
                }
                return _parseFloat(p, ctxt);
            }
    
            protected final Float _parseFloat(JsonParser p, DeserializationContext ctxt)
                throws IOException
            {
                String text;
                switch (p.currentTokenId()) {
                case JsonTokenId.ID_STRING:
                    text = p.getText();
                    break;
                case JsonTokenId.ID_NULL: // null fine for non-primitive
                    return (Float) getNullValue(ctxt);
                case JsonTokenId.ID_NUMBER_FLOAT:
                case JsonTokenId.ID_NUMBER_INT: // safe coercion
                    return p.getFloatValue();
                // 29-Jun-2020, tatu: New! "Scalar from Object" (mostly for XML)
                case JsonTokenId.ID_START_OBJECT:
                    text = ctxt.extractScalarFromObject(p, this, _valueClass);
                    break;
                case JsonTokenId.ID_START_ARRAY:
                    return _deserializeFromArray(p, ctxt);
                default:
                    return (Float) ctxt.handleUnexpectedToken(getValueType(ctxt), p);
                }
    
                // 18-Nov-2020, tatu: Special case, Not-a-Numbers as String need to be
                //     considered "native" representation as JSON does not allow as numbers,
                //     and hence not bound by coercion rules
                {
                    Float nan = _checkFloatSpecialValue(text);
                    if (nan != null) {
                        return nan;
                    }
                }
                final CoercionAction act = _checkFromStringCoercion(ctxt, text);
                if (act == CoercionAction.AsNull) {
                    return (Float) getNullValue(ctxt);
                }
                if (act == CoercionAction.AsEmpty) {
                    return (Float) getEmptyValue(ctxt);
                }
                text = text.trim();
                if (_checkTextualNull(ctxt, text)) {
                    return (Float) getNullValue(ctxt);
                }
                try {
                    return Float.parseFloat(text);
                } catch (IllegalArgumentException iae) { }
                return (Float) ctxt.handleWeirdStringValue(_valueClass, text,
                        "not a valid `Float` value");
            }
        }
    
        @JacksonStdImpl
        public static class DoubleDeserializer
            extends PrimitiveOrWrapperDeserializer<Double>
        {
            private static final long serialVersionUID = 1L;
    
            final static DoubleDeserializer primitiveInstance = new DoubleDeserializer(Double.TYPE, 0.d);
            final static DoubleDeserializer wrapperInstance = new DoubleDeserializer(Double.class, null);
            
            public DoubleDeserializer(Class<Double> cls, Double nvl) {
                super(cls, LogicalType.Float, nvl, 0.d);
            }
    
            @Override
            public Double deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
                if (p.hasToken(JsonToken.VALUE_NUMBER_FLOAT)) {
                    return p.getDoubleValue();
                }
                if (_primitive) {
                    return _parseDoublePrimitive(p, ctxt);
                }
                return _parseDouble(p, ctxt);
            }
    
            // Since we can never have type info ("natural type"; String, Boolean, Integer, Double):
            // (is it an error to even call this version?)
            @Override
            public Double deserializeWithType(JsonParser p, DeserializationContext ctxt,
                    TypeDeserializer typeDeserializer) throws IOException
            {
                if (p.hasToken(JsonToken.VALUE_NUMBER_FLOAT)) {
                    return p.getDoubleValue();
                }
                if (_primitive) {
                    return _parseDoublePrimitive(p, ctxt);
                }
                return _parseDouble(p, ctxt);
            }
    
            protected final Double _parseDouble(JsonParser p, DeserializationContext ctxt) throws IOException
            {
                String text;
                switch (p.currentTokenId()) {
                case JsonTokenId.ID_STRING:
                    text = p.getText();
                    break;
                case JsonTokenId.ID_NULL: // null fine for non-primitive
                    return (Double) getNullValue(ctxt);
                case JsonTokenId.ID_NUMBER_FLOAT:
                case JsonTokenId.ID_NUMBER_INT: // safe coercion
                    return p.getDoubleValue();
                // 29-Jun-2020, tatu: New! "Scalar from Object" (mostly for XML)
                case JsonTokenId.ID_START_OBJECT:
                    text = ctxt.extractScalarFromObject(p, this, _valueClass);
                    break;
                case JsonTokenId.ID_START_ARRAY:
                    return _deserializeFromArray(p, ctxt);
                default:
                    return (Double) ctxt.handleUnexpectedToken(getValueType(ctxt), p);
                }
    
                // 18-Nov-2020, tatu: Special case, Not-a-Numbers as String need to be
                //     considered "native" representation as JSON does not allow as numbers,
                //     and hence not bound by coercion rules
                {
                    Double nan = this._checkDoubleSpecialValue(text);
                    if (nan != null) {
                        return nan;
                    }
                }
    
                // Coercion from String most complicated
                final CoercionAction act = _checkFromStringCoercion(ctxt, text);
                if (act == CoercionAction.AsNull) {
                    return (Double) getNullValue(ctxt);
                }
                if (act == CoercionAction.AsEmpty) {
                    return (Double) getEmptyValue(ctxt);
                }
                text = text.trim();
                if (_checkTextualNull(ctxt, text)) {
                    return (Double) getNullValue(ctxt);
                }
                try {
                    return _parseDouble(text);
                } catch (IllegalArgumentException iae) { }
                return (Double) ctxt.handleWeirdStringValue(_valueClass, text,
                        "not a valid `Double` value");
            }
        }
    
        /**
         * For type <code>Number.class</code>, we can just rely on type
         * mappings that plain {@link JsonParser#getNumberValue} returns.
         *<p>
         * There is one additional complication: some numeric
         * types (specifically, int/Integer and double/Double) are "non-typed";
         * meaning that they will NEVER be output with type information.
         * But other numeric types may need such type information.
         * This is why {@link #deserializeWithType} must be overridden.
         */
        @SuppressWarnings("serial")
        @JacksonStdImpl
        public static class NumberDeserializer
            extends StdScalarDeserializer<Object>
        {
            public final static NumberDeserializer instance = new NumberDeserializer();
            
            public NumberDeserializer() {
                super(Number.class);
            }
    
            @Override // since 2.12
            public final LogicalType logicalType() {
                // 07-Jun-2020, tatu: Hmmh... tricky choice. For now, use:
                return LogicalType.Integer;
            }
    
            @Override
            public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
            {
                String text;
                switch (p.currentTokenId()) {
                case JsonTokenId.ID_STRING:
                    text = p.getText();
                    break;
                case JsonTokenId.ID_NUMBER_INT:
                    if (ctxt.hasSomeOfFeatures(F_MASK_INT_COERCIONS)) {
                        return _coerceIntegral(p, ctxt);
                    }
                    return p.getNumberValue();
    
                case JsonTokenId.ID_NUMBER_FLOAT:
                    if (ctxt.isEnabled(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)) {
                        // 10-Mar-2017, tatu: NaN and BigDecimal won't mix...
                        if (!p.isNaN()) {
                            return p.getDecimalValue();
                        }
                    }
                    return p.getNumberValue();
                // 29-Jun-2020, tatu: New! "Scalar from Object" (mostly for XML)
                case JsonTokenId.ID_START_OBJECT:
                    text = ctxt.extractScalarFromObject(p, this, _valueClass);
                    break;
                case JsonTokenId.ID_START_ARRAY:
                    return _deserializeFromArray(p, ctxt);
                default:
                    return ctxt.handleUnexpectedToken(getValueType(ctxt), p);
                }
    
                // Textual values are more difficult... not parsing itself, but figuring
                // out 'minimal' type to use 
                CoercionAction act = _checkFromStringCoercion(ctxt, text);
                if (act == CoercionAction.AsNull) {
                    return getNullValue(ctxt);
                }
                if (act == CoercionAction.AsEmpty) {
                    return getEmptyValue(ctxt);
                }
                text = text.trim();
                if (_hasTextualNull(text)) {
                    // note: no need to call `coerce` as this is never primitive
                    return getNullValue(ctxt);
                }
                if (_isPosInf(text)) {
                    return Double.POSITIVE_INFINITY;
                }
                if (_isNegInf(text)) {
                    return Double.NEGATIVE_INFINITY;
                }
                if (_isNaN(text)) {
                    return Double.NaN;
                }
                try {
                    if (!_isIntNumber(text)) {
                        if (ctxt.isEnabled(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)) {
                            return new BigDecimal(text);
                        }
                        return Double.valueOf(text);
                    }
                    if (ctxt.isEnabled(DeserializationFeature.USE_BIG_INTEGER_FOR_INTS)) {
                        return new BigInteger(text);
                    }
                    long value = Long.parseLong(text);
                    if (!ctxt.isEnabled(DeserializationFeature.USE_LONG_FOR_INTS)) {
                        if (value <= Integer.MAX_VALUE && value >= Integer.MIN_VALUE) {
                            return Integer.valueOf((int) value);
                        }
                    }
                    return Long.valueOf(value);
                } catch (IllegalArgumentException iae) {
                    return ctxt.handleWeirdStringValue(_valueClass, text,
                            "not a valid number");
                }
            }
    
            /**
             * As mentioned in class Javadoc, there is additional complexity in
             * handling potentially mixed type information here. Because of this,
             * we must actually check for "raw" integers and doubles first, before
             * calling type deserializer.
             */
            @Override
            public Object deserializeWithType(JsonParser p, DeserializationContext ctxt,
                    TypeDeserializer typeDeserializer)
                throws IOException
            {
                switch (p.currentTokenId()) {
                case JsonTokenId.ID_NUMBER_INT:
                case JsonTokenId.ID_NUMBER_FLOAT:
                case JsonTokenId.ID_STRING:
                    // cannot point to type information: hence must be non-typed (int/double)
                    return deserialize(p, ctxt);
                }
                return typeDeserializer.deserializeTypedFromScalar(p, ctxt);
            }
        }
    
        /*
        /**********************************************************
        /* And then bit more complicated (but non-structured) number types
        /**********************************************************
         */
    
        /**
         * This is bit trickier to implement efficiently, while avoiding
         * overflow problems.
         */
        @SuppressWarnings("serial")
        @JacksonStdImpl
        public static class BigIntegerDeserializer
            extends StdScalarDeserializer<BigInteger>
        {
            public final static BigIntegerDeserializer instance = new BigIntegerDeserializer();
    
            public BigIntegerDeserializer() { super(BigInteger.class); }
    
            @Override
            public Object getEmptyValue(DeserializationContext ctxt) {
                return BigInteger.ZERO;
            }
    
            @Override // since 2.12
            public final LogicalType logicalType() {
                return LogicalType.Integer;
            }
    
            @Override
            public BigInteger deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
            {
                if (p.isExpectedNumberIntToken()) {
                    return p.getBigIntegerValue();
                }
    
                String text;
                switch (p.currentTokenId()) {
                case JsonTokenId.ID_STRING: // let's do implicit re-parse
                    text = p.getText();
                    break;
                case JsonTokenId.ID_NUMBER_FLOAT:
                    final CoercionAction act = _checkFloatToIntCoercion(p, ctxt, _valueClass);
                    if (act == CoercionAction.AsNull) {
                        return (BigInteger) getNullValue(ctxt);
                    }
                    if (act == CoercionAction.AsEmpty) {
                        return (BigInteger) getEmptyValue(ctxt);
                    }
                    return p.getDecimalValue().toBigInteger();
                // 29-Jun-2020, tatu: New! "Scalar from Object" (mostly for XML)
                case JsonTokenId.ID_START_OBJECT:
                    text = ctxt.extractScalarFromObject(p, this, _valueClass);
                    break;
                case JsonTokenId.ID_START_ARRAY:
                    return _deserializeFromArray(p, ctxt);
                default:
                    // String is ok too, can easily convert; otherwise, no can do:
                    return (BigInteger) ctxt.handleUnexpectedToken(getValueType(ctxt), p);
                }
    
                final CoercionAction act = _checkFromStringCoercion(ctxt, text);
                if (act == CoercionAction.AsNull) {
                    return getNullValue(ctxt);
                }
                if (act == CoercionAction.AsEmpty) {
                    return (BigInteger) getEmptyValue(ctxt);
                }
                text = text.trim();
                if (_hasTextualNull(text)) {
                    // note: no need to call `coerce` as this is never primitive
                    return getNullValue(ctxt);
                }
                try {
                    return new BigInteger(text);
                } catch (IllegalArgumentException iae) { }
                return (BigInteger) ctxt.handleWeirdStringValue(_valueClass, text,
                        "not a valid representation");
            }
        }
    
        @SuppressWarnings("serial")
        @JacksonStdImpl
        public static class BigDecimalDeserializer
            extends StdScalarDeserializer<BigDecimal>
        {
            public final static BigDecimalDeserializer instance = new BigDecimalDeserializer();
     
            public BigDecimalDeserializer() { super(BigDecimal.class); }
    
            @Override
            public Object getEmptyValue(DeserializationContext ctxt) {
                return BigDecimal.ZERO;
            }
    
            @Override // since 2.12
            public final LogicalType logicalType() {
                return LogicalType.Float;
            }
    
            @Override
            public BigDecimal deserialize(JsonParser p, DeserializationContext ctxt)
                throws IOException
            {
                String text;
                switch (p.currentTokenId()) {
                case JsonTokenId.ID_NUMBER_INT:
                case JsonTokenId.ID_NUMBER_FLOAT:
                    return p.getDecimalValue();
                case JsonTokenId.ID_STRING:
                    text = p.getText();
                    break;
                // 29-Jun-2020, tatu: New! "Scalar from Object" (mostly for XML)
                case JsonTokenId.ID_START_OBJECT:
                    text = ctxt.extractScalarFromObject(p, this, _valueClass);
                    break;
                case JsonTokenId.ID_START_ARRAY:
                    return _deserializeFromArray(p, ctxt);
                default:
                    return (BigDecimal) ctxt.handleUnexpectedToken(getValueType(ctxt), p);
                }
    
                final CoercionAction act = _checkFromStringCoercion(ctxt, text);
                if (act == CoercionAction.AsNull) {
                    return getNullValue(ctxt);
                }
                if (act == CoercionAction.AsEmpty) {
                    return (BigDecimal) getEmptyValue(ctxt);
                }
                text = text.trim();
                if (_hasTextualNull(text)) {
                    // note: no need to call `coerce` as this is never primitive
                    return getNullValue(ctxt);
                }
                try {
                    return new BigDecimal(text);
                } catch (IllegalArgumentException iae) { }
                return (BigDecimal) ctxt.handleWeirdStringValue(_valueClass, text,
                        "not a valid representation");
            }
        }
    }
    

    com/fasterxml/jackson/databind/deser/std/NumberDeserializers.java

     

    ⇒ Jackson Annotations Source Code

    ⇐ Download and Install Jackson Binary Package

    ⇑ Downloading and Reviewing jackson-*.jar

    ⇑⇑ Jackson - Java JSON library

    2022-03-29, 31917👍, 0💬