Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  package com.fasterxml.jackson.databind.deser.std;
  
  
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
 {
     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()
         };
     }
     
     /*
     /**********************************************************
     /* 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
     /**********************************************************
      */
 
     @JacksonStdImpl
     public final static class BooleanDeserializer
         extends PrimitiveOrWrapperDeserializer<Boolean>
     {
         private static final long serialVersionUID = 1L;
 
         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>
    {
        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>
    {
        public ShortDeserializer(Class<ShortclsShort nvl)
        {
            super(clsnvl);
        }
        @Override
        public Short deserialize(JsonParser jpDeserializationContext ctxt)
            throws IOExceptionJsonProcessingException
        {
            return _parseShort(jpctxt);
        }
    }
    public final static class CharacterDeserializer
    {
        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;
        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;
        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;
        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;
        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 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.
        @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 BigIntegerDeserializer() { super(BigInteger.class); }
        @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 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);
        }
    }