Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  package com.fasterxml.jackson.databind.deser.std;
  
  import java.util.HashSet;
  
 
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 java.lang.Boolean and 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.classBigDecimal.classBigInteger.class
         };
         for (Class<?> cls : numberTypes) {
             .add(cls.getName());
         }
     }

    

Deprecated:
Since 2.2 -- use find(java.lang.Class,java.lang.String) instead.
 
     @Deprecated
     public static StdDeserializer<?>[] all()
     {
         return new StdDeserializer<?>[] {
                 // primitive-wrappers (simple):
                 new BooleanDeserializer(Boolean.classnull),
                 new ByteDeserializer(Byte.classnull),
                 new ShortDeserializer(Short.classnull),
                 new CharacterDeserializer(Character.classnull),
                 new IntegerDeserializer(Integer.classnull),
                 new LongDeserializer(Long.classnull),
                 new FloatDeserializer(Float.classnull),
                 new DoubleDeserializer(Double.classnull),
 
                 /* And actual primitives: difference is the way nulls are to be
                  * handled...
                  */
                 new BooleanDeserializer(..),
                 new ByteDeserializer(., Byte.valueOf((byte)(0))),
                 new ShortDeserializer(., Short.valueOf((short)0)),
                 new CharacterDeserializer(., Character.valueOf('\0')),
                 new IntegerDeserializer(., Integer.valueOf(0)),
                 new LongDeserializer(., Long.valueOf(0L)),
                 new FloatDeserializer(., Float.valueOf(0.0f)),
                 new DoubleDeserializer(., Double.valueOf(0.0)),
                 
                 // and related
                 new NumberDeserializer(),
                 new BigDecimalDeserializer(),
                 new BigIntegerDeserializer()
         };
     }
     
     public static JsonDeserializer<?> find(Class<?> rawTypeString clsName)
     {
         if (rawType.isPrimitive()) {
             if (rawType == .) {
                 return .;
             }
             if (rawType == .) {
                 return .;
             }
             if (rawType == .) {
                 return .;
             }
             if (rawType == .) {
                 return .;
             }
             if (rawType == .) {
                 return .;
            }
            if (rawType == .) {
                return .;
            }
            if (rawType == .) {
                return .;
            }
            if (rawType == .) {
                return .;
            }
        } else if (.contains(clsName)) {
            // Start with most common types; int, boolean, long, double
            if (rawType == Integer.class) {
                return .;
            }
            if (rawType == Boolean.class) {
                return .;
            }
            if (rawType == Long.class) {
                return .;
            }
            if (rawType == Double.class) {
                return .;
            }
            if (rawType == Character.class) {
                return .;
            }
            if (rawType == Byte.class) {
                return .;
            }
            if (rawType == Short.class) {
                return .;
            }
            if (rawType == Float.class) {
                return .;
            }
            if (rawType == Number.class) {
                return .;
            }
            if (rawType == BigDecimal.class) {
                return .;
            }
            if (rawType == BigInteger.class) {
                return .;
            }
        } 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;
        protected final T _nullValue;
        
        protected PrimitiveOrWrapperDeserializer(Class<T> vc, T nvl)
        {
            super(vc);
             = nvl;
        }
        
        @Override
        public final T getNullValue() {
            return ;
        }
    }
    
    /*
    /**********************************************************
    /* Then primitive/wrapper types
    /**********************************************************
     */
    public final static class BooleanDeserializer
        extends PrimitiveOrWrapperDeserializer<Boolean>
    {
        private static final long serialVersionUID = 1L;
        private final static BooleanDeserializer primitiveInstance = new BooleanDeserializer(Boolean.class.);
        private final static BooleanDeserializer wrapperInstance = new BooleanDeserializer(.null);
        
        public BooleanDeserializer(Class<BooleanclsBoolean nvl)
        {
            super(clsnvl);
        }
        
        @Override
        public Boolean deserialize(JsonParser jpDeserializationContext ctxt)
            throws IOExceptionJsonProcessingException
        {
            return _parseBoolean(jpctxt);
        }
        // 1.6: 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 jpDeserializationContext ctxt,
                TypeDeserializer typeDeserializer)
            throws IOExceptionJsonProcessingException
        {
            return _parseBoolean(jpctxt);
        }
    }
    public final static class ByteDeserializer
        extends PrimitiveOrWrapperDeserializer<Byte>
    {
        private static final long serialVersionUID = 1L;
        private final static ByteDeserializer primitiveInstance = new ByteDeserializer(., (byte) 0);
        private final static ByteDeserializer wrapperInstance = new ByteDeserializer(Byte.classnull);
        
        public ByteDeserializer(Class<ByteclsByte nvl)
        {
            super(clsnvl);
        }
        @Override
        public Byte deserialize(JsonParser jpDeserializationContext ctxt)
            throws IOExceptionJsonProcessingException
        {
            return _parseByte(jpctxt);
        }
    }
    public final static class ShortDeserializer
        extends PrimitiveOrWrapperDeserializer<Short>
    {
        private static final long serialVersionUID = 1L;
        private final static ShortDeserializer primitiveInstance = new ShortDeserializer(Short.class, Short.valueOf((short)0));
        private final static ShortDeserializer wrapperInstance = new ShortDeserializer(.null);
        
        public ShortDeserializer(Class<ShortclsShort nvl)
        {
            super(clsnvl);
        }
        @Override
        public Short deserialize(JsonParser jpDeserializationContext ctxt)
            throws IOExceptionJsonProcessingException
        {
            return _parseShort(jpctxt);
        }
    }
    public final static class CharacterDeserializer
    {
        private static final long serialVersionUID = 1L;
        private final static CharacterDeserializer primitiveInstance = new CharacterDeserializer(Character.class'\0');
        private final static CharacterDeserializer wrapperInstance = new CharacterDeserializer(.null);
        
        public CharacterDeserializer(Class<CharacterclsCharacter nvl)
        {
            super(clsnvl);
        }
        @Override
        public Character deserialize(JsonParser jpDeserializationContext ctxt)
            throws IOExceptionJsonProcessingException
        {
            JsonToken t = jp.getCurrentToken();
            int value;
            if (t == .) { // ok iff ascii value
                value = jp.getIntValue();
                if (value >= 0 && value <= 0xFFFF) {
                    return Character.valueOf((charvalue);
                }
            } else if (t == .) { // this is the usual type
                // But does it have to be exactly one char?
                String text = jp.getText();
                if (text.length() == 1) {
                    return Character.valueOf(text.charAt(0));
                }
                // actually, empty should become null?
                if (text.length() == 0) {
                    return (CharactergetEmptyValue();
                }
            }
            throw ctxt.mappingException(t);
        }
    }
    public final static class IntegerDeserializer
        extends PrimitiveOrWrapperDeserializer<Integer>
    {
        private static final long serialVersionUID = 1L;
        private final static IntegerDeserializer primitiveInstance = new IntegerDeserializer(Integer.class, 0);
        private final static IntegerDeserializer wrapperInstance = new IntegerDeserializer(.null);
        
        public IntegerDeserializer(Class<IntegerclsInteger nvl)
        {
            super(clsnvl);
        }
        @Override
        public Integer deserialize(JsonParser jpDeserializationContext ctxt)
            throws IOExceptionJsonProcessingException
        {
            return _parseInteger(jpctxt);
        }
        // 1.6: 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 jpDeserializationContext ctxt,
                TypeDeserializer typeDeserializer)
            throws IOExceptionJsonProcessingException
        {
            return _parseInteger(jpctxt);
        }
    }
    public final static class LongDeserializer
        extends PrimitiveOrWrapperDeserializer<Long>
    {
        private static final long serialVersionUID = 1L;
        private final static LongDeserializer primitiveInstance = new LongDeserializer(Long.class, Long.valueOf(0L));
        private final static LongDeserializer wrapperInstance = new LongDeserializer(.null);
        
        public LongDeserializer(Class<LongclsLong nvl)
        {
            super(clsnvl);
        }
        @Override
        public Long deserialize(JsonParser jpDeserializationContext ctxt)
            throws IOExceptionJsonProcessingException
        {
            return _parseLong(jpctxt);
        }
    }
    public final static class FloatDeserializer
        extends PrimitiveOrWrapperDeserializer<Float>
    {
        private static final long serialVersionUID = 1L;
        private final static FloatDeserializer primitiveInstance = new FloatDeserializer(Float.class, 0.f);
        private final static FloatDeserializer wrapperInstance = new FloatDeserializer(.null);
        
        public FloatDeserializer(Class<FloatclsFloat nvl)
        {
            super(clsnvl);
        }
        @Override
        public Float deserialize(JsonParser jpDeserializationContext ctxt)
            throws IOExceptionJsonProcessingException
        {
            /* 22-Jan-2009, tatu: Bounds/range checks would be tricky
             *   here, so let's not bother even trying...
             */
            return _parseFloat(jpctxt);
        }
    }
    public final static class DoubleDeserializer
        extends PrimitiveOrWrapperDeserializer<Double>
    {
        private static final long serialVersionUID = 1L;
        private final static DoubleDeserializer primitiveInstance = new DoubleDeserializer(Double.class, 0.d);
        private final static DoubleDeserializer wrapperInstance = new DoubleDeserializer(.null);
        
        public DoubleDeserializer(Class<DoubleclsDouble nvl)
        {
            super(clsnvl);
        }
        @Override
        public Double deserialize(JsonParser jpDeserializationContext ctxt)
            throws IOExceptionJsonProcessingException
        {
            return _parseDouble(jpctxt);
        }
        // 1.6: 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 jpDeserializationContext ctxt,
                TypeDeserializer typeDeserializer)
            throws IOExceptionJsonProcessingException
        {
            return _parseDouble(jpctxt);
        }
    }

    
For type Number.class, we can just rely on type mappings that plain com.fasterxml.jackson.core.JsonParser.getNumberValue() returns.

Since 1.5, 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 deserializeWithType(com.fasterxml.jackson.core.JsonParser,com.fasterxml.jackson.databind.DeserializationContext,com.fasterxml.jackson.databind.jsontype.TypeDeserializer) must be overridden.

    @SuppressWarnings("serial")
    public final static class NumberDeserializer
        extends StdScalarDeserializer<Number>
    {
        public final static NumberDeserializer instance = new NumberDeserializer();
        
        public NumberDeserializer() { super(Number.class); }
        @Override
        public Number deserialize(JsonParser jpDeserializationContext ctxt)
            throws IOExceptionJsonProcessingException
        {
            JsonToken t = jp.getCurrentToken();
            if (t == .) {
                if (ctxt.isEnabled(.)) {
                    return jp.getBigIntegerValue();
                }
                return jp.getNumberValue();
            } else if (t == .) {
                /* [JACKSON-72]: need to allow overriding the behavior
                 * regarding which type to use
                 */
                if (ctxt.isEnabled(.)) {
                    return jp.getDecimalValue();
                }
                return Double.valueOf(jp.getDoubleValue());
            }
            /* Textual values are more difficult... not parsing itself, but figuring
             * out 'minimal' type to use 
             */
            if (t == .) { // let's do implicit re-parse
                String text = jp.getText().trim();
                try {
                    if (text.indexOf('.') >= 0) { // floating point
                        // as per [JACKSON-72]:
                        if (ctxt.isEnabled(.)) {
                            return new BigDecimal(text);
                        }
                        return new Double(text);
                    }
                    // as per [JACKSON-100]:
                    if (ctxt.isEnabled(.)) {
                        return new BigInteger(text);
                    }
                    long value = Long.parseLong(text);
                    if (value <= . && value >= .) {
                        return Integer.valueOf((intvalue);
                    }
                    return Long.valueOf(value);
                } catch (IllegalArgumentException iae) {
                    throw ctxt.weirdStringException(text"not a valid number");
                }
            }
            // Otherwise, no can do:
            throw ctxt.mappingException(t);
        }

        
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.
        @SuppressWarnings("incomplete-switch")
        @Override
        public Object deserializeWithType(JsonParser jpDeserializationContext ctxt,
                                          TypeDeserializer typeDeserializer)
            throws IOExceptionJsonProcessingException
        {
            switch (jp.getCurrentToken()) {
            case :
            case :
            case :
                // can not point to type information: hence must be non-typed (int/double)
                return deserialize(jpctxt);
            }
            return typeDeserializer.deserializeTypedFromScalar(jpctxt);
        }
    }
    /*
    /**********************************************************
    /* And then bit more complicated (but non-structured) number
    /* types
    /**********************************************************
     */
    
    
This is bit trickier to implement efficiently, while avoiding overflow problems.
    @SuppressWarnings("serial")
    public static class BigIntegerDeserializer
        extends StdScalarDeserializer<BigInteger>
    {
        public final static BigIntegerDeserializer instance = new BigIntegerDeserializer();
        public BigIntegerDeserializer() { super(BigInteger.class); }
        @SuppressWarnings("incomplete-switch")
        @Override
        public BigInteger deserialize(JsonParser jpDeserializationContext ctxt)
            throws IOExceptionJsonProcessingException
        {
            JsonToken t = jp.getCurrentToken();
            String text;
            if (t == .) {
                switch (jp.getNumberType()) {
                case :
                case :
                    return BigInteger.valueOf(jp.getLongValue());
                }
            } else if (t == .) {
                /* Whether to fail if there's non-integer part?
                 * Could do by calling BigDecimal.toBigIntegerExact()
                 */
                return jp.getDecimalValue().toBigInteger();
            } else if (t != .) { // let's do implicit re-parse
                // String is ok too, can easily convert; otherwise, no can do:
                throw ctxt.mappingException(t);
            }
            text = jp.getText().trim();
            if (text.length() == 0) {
                return null;
            }
            try {
                return new BigInteger(text);
            } catch (IllegalArgumentException iae) {
                throw ctxt.weirdStringException(text"not a valid representation");
            }
        }
    }
    
    @SuppressWarnings("serial")
    public static class BigDecimalDeserializer
        extends StdScalarDeserializer<BigDecimal>
    {
        public final static BigDecimalDeserializer instance = new BigDecimalDeserializer();
 
        public BigDecimalDeserializer() { super(BigDecimal.class); }
        @Override
        public BigDecimal deserialize(JsonParser jpDeserializationContext ctxt)
            throws IOExceptionJsonProcessingException
        {
            JsonToken t = jp.getCurrentToken();
            if (t == . || t == .) {
                return jp.getDecimalValue();
            }
            // String is ok too, can easily convert
            if (t == .) { // let's do implicit re-parse
                String text = jp.getText().trim();
                if (text.length() == 0) {
                    return null;
                }
                try {
                    return new BigDecimal(text);
                } catch (IllegalArgumentException iae) {
                    throw ctxt.weirdStringException(text"not a valid representation");
                }
            }
            // Otherwise, no can do:
            throw ctxt.mappingException(t);
        }
    }