Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  package com.fasterxml.jackson.databind.deser.std;
  
  import java.util.*;
  
Container for deserializers used for instantiating "primitive arrays", arrays that contain non-object java primitive types.
 
 {
 
 
     protected PrimitiveArrayDeserializers()
     {
         // note: we'll use component type as key, not array type
         add(boolean.classnew BooleanDeser());
 
         /* ByteDeser is bit special, as it has 2 separate modes of operation;
          * one for String input (-> base64 input), the other for
          * numeric input
          */
         add(byte.classnew ByteDeser());
         add(short.classnew ShortDeser());
         add(int.classnew IntDeser());
         add(long.classnew LongDeser());
 
         add(float.classnew FloatDeser());
         add(double.classnew DoubleDeser());
 
         add(String.classnew StringDeser());
         /* also: char[] is most likely only used with Strings; doesn't
          * seem to make sense to transfer as numbers
          */
         add(char.classnew CharDeser());
     }
 
     public static HashMap<JavaType,JsonDeserializer<Object>> getAll()
     {
         return .;
     }
 
     @SuppressWarnings("unchecked")
     private void add(Class<?> clsJsonDeserializer<?> deser)
     {
         /* Not super clean to use default TypeFactory in general, but
          * since primitive array types can't be modified for anything
          * useful, this should be ok:
          */
         .put(TypeFactory.defaultInstance().constructType(cls),
                 (JsonDeserializer<Object>) deser);
     }
 
             TypeDeserializer typeDeserializer)
         throws IOExceptionJsonProcessingException
     {
         /* Should there be separate handling for base64 stuff?
          * for now this should be enough:
          */
         return typeDeserializer.deserializeTypedFromArray(jpctxt);
     }
 
     /*
     /********************************************************
     /* Intermediate base class
     /********************************************************
      */
    
    
Intermediate base class for primitive array deserializers
 
     static abstract class Base<T> extends StdDeserializer<T>
     {
         private static final long serialVersionUID = 1L;
 
         protected Base(Class<T> cls) {
             super(cls);
         }
 
         @Override
         public Object deserializeWithType(JsonParser jpDeserializationContext ctxt,
             TypeDeserializer typeDeserializer)
             throws IOExceptionJsonProcessingException
         {
             return typeDeserializer.deserializeTypedFromArray(jpctxt);
         }
    }
    
    /*
    /********************************************************
    /* Actual deserializers: efficient String[], char[] deserializers
    /********************************************************
    */
    final static class StringDeser
        extends Base<String[]>
    {
        private static final long serialVersionUID = 1L;
        public StringDeser() { super(String[].class); }
        @Override
        public String[] deserialize(JsonParser jpDeserializationContext ctxt)
            throws IOExceptionJsonProcessingException
        {
            // Ok: must point to START_ARRAY (or equivalent)
            if (!jp.isExpectedStartArrayToken()) {
                return handleNonArray(jpctxt);
            }
            final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
            Object[] chunk = buffer.resetAndStart();
            int ix = 0;
            JsonToken t;
            
            while ((t = jp.nextToken()) != .) {
                // Ok: no need to convert Strings, but must recognize nulls
                String value = (t == .) ? null : _parseString(jpctxt);
                if (ix >= chunk.length) {
                    chunk = buffer.appendCompletedChunk(chunk);
                    ix = 0;
                }
                chunk[ix++] = value;
            }
            String[] result = buffer.completeAndClearBuffer(chunkixString.class);
            ctxt.returnObjectBuffer(buffer);
            return result;
        }
    
        private final String[] handleNonArray(JsonParser jpDeserializationContext ctxt)
            throws IOExceptionJsonProcessingException
        {
            // [JACKSON-526]: implicit arrays from single values?
            if (!ctxt.isEnabled(.)) {
                // [JACKSON-620] Empty String can become null...
                if ((jp.getCurrentToken() == .)
                        && ctxt.isEnabled(.)) {
                    String str = jp.getText();
                    if (str.length() == 0) {
                        return null;
                    }
                }
                throw ctxt.mappingException();
            }
            return new String[] { (jp.getCurrentToken() == .) ? null : _parseString(jpctxt) };
        }
    }
    
    final static class CharDeser
        extends Base<char[]>
    {
        private static final long serialVersionUID = 1L;
        public CharDeser() { super(char[].class); }
        @Override
        public char[] deserialize(JsonParser jpDeserializationContext ctxt)
            throws IOExceptionJsonProcessingException
        {
            /* Won't take arrays, must get a String (could also
             * convert other tokens to Strings... but let's not bother
             * yet, doesn't seem to make sense)
             */
            JsonToken t = jp.getCurrentToken();
            if (t == .) {
                // note: can NOT return shared internal buffer, must copy:
                char[] buffer = jp.getTextCharacters();
                int offset = jp.getTextOffset();
                int len = jp.getTextLength();
    
                char[] result = new char[len];
                System.arraycopy(bufferoffsetresult, 0, len);
                return result;
            }
            if (jp.isExpectedStartArrayToken()) {
                // Let's actually build as a String, then get chars
                StringBuilder sb = new StringBuilder(64);
                while ((t = jp.nextToken()) != .) {
                    if (t != .) {
                        throw ctxt.mappingException(.);
                    }
                    String str = jp.getText();
                    if (str.length() != 1) {
                        throw JsonMappingException.from(jp"Can not convert a JSON String of length "+str.length()+" into a char element of char array");
                    }
                    sb.append(str.charAt(0));
                }
                return sb.toString().toCharArray();
            }
            // or, maybe an embedded object?
            if (t == .) {
                Object ob = jp.getEmbeddedObject();
                if (ob == nullreturn null;
                if (ob instanceof char[]) {
                    return (char[]) ob;
                }
                if (ob instanceof String) {
                    return ((Stringob).toCharArray();
                }
                // 04-Feb-2011, tatu: byte[] can be converted; assuming base64 is wanted
                if (ob instanceof byte[]) {
                    return Base64Variants.getDefaultVariant().encode((byte[]) obfalse).toCharArray();
                }
                // not recognized, just fall through
            }
            throw ctxt.mappingException();
        }
    }
    /*
    /********************************************************
    /* Actual deserializers: primivate array desers
    /********************************************************
    */
    final static class BooleanDeser
        extends Base<boolean[]>
    {
        private static final long serialVersionUID = 1L;
        public BooleanDeser() { super(boolean[].class); }
        @Override
        public boolean[] deserialize(JsonParser jpDeserializationContext ctxt)
            throws IOExceptionJsonProcessingException
        {
            if (!jp.isExpectedStartArrayToken()) {
                return handleNonArray(jpctxt);
            }
            ArrayBuilders.BooleanBuilder builder = ctxt.getArrayBuilders().getBooleanBuilder();
            boolean[] chunk = builder.resetAndStart();
            int ix = 0;
            while (jp.nextToken() != .) {
                // whether we should allow truncating conversions?
                boolean value = _parseBooleanPrimitive(jpctxt);
                if (ix >= chunk.length) {
                    chunk = builder.appendCompletedChunk(chunkix);
                    ix = 0;
                }
                chunk[ix++] = value;
            }
            return builder.completeAndClearBuffer(chunkix);
        }
        private final boolean[] handleNonArray(JsonParser jpDeserializationContext ctxt)
            throws IOExceptionJsonProcessingException
        {
            // [JACKSON-620] Empty String can become null...
            if ((jp.getCurrentToken() == .)
                    && ctxt.isEnabled(.)) {
                if (jp.getText().length() == 0) {
                    return null;
                }
            }
            if (!ctxt.isEnabled(.)) {
                throw ctxt.mappingException();
            }
            return new boolean[] { _parseBooleanPrimitive(jpctxt) };
        }
    }

    
When dealing with byte arrays we have one more alternative (compared to int/long/shorts): base64 encoded data.
    final static class ByteDeser
        extends Base<byte[]>
    {
        private static final long serialVersionUID = 1L;
        public ByteDeser() { super(byte[].class); }
        @Override
        public byte[] deserialize(JsonParser jpDeserializationContext ctxt)
            throws IOExceptionJsonProcessingException
        {
            JsonToken t = jp.getCurrentToken();
            
            // Most likely case: base64 encoded String?
            if (t == .) {
                return jp.getBinaryValue(ctxt.getBase64Variant());
            }
            // 31-Dec-2009, tatu: Also may be hidden as embedded Object
            if (t == .) {
                Object ob = jp.getEmbeddedObject();
                if (ob == nullreturn null;
                if (ob instanceof byte[]) {
                    return (byte[]) ob;
                }
            }
            if (!jp.isExpectedStartArrayToken()) {
                return handleNonArray(jpctxt);
            }
            ArrayBuilders.ByteBuilder builder = ctxt.getArrayBuilders().getByteBuilder();
            byte[] chunk = builder.resetAndStart();
            int ix = 0;
            while ((t = jp.nextToken()) != .) {
                // whether we should allow truncating conversions?
                byte value;
                if (t == . || t == .) {
                    // should we catch overflow exceptions?
                    value = jp.getByteValue();
                } else {
                    // [JACKSON-79]: should probably accept nulls as 0
                    if (t != .) {
                        throw ctxt.mappingException(.getComponentType());
                    }
                    value = (byte) 0;
                }
                if (ix >= chunk.length) {
                    chunk = builder.appendCompletedChunk(chunkix);
                    ix = 0;
                }
                chunk[ix++] = value;
            }
            return builder.completeAndClearBuffer(chunkix);
        }
        private final byte[] handleNonArray(JsonParser jpDeserializationContext ctxt)
            throws IOExceptionJsonProcessingException
        {
            // [JACKSON-620] Empty String can become null...
            if ((jp.getCurrentToken() == .)
                    && ctxt.isEnabled(.)) {
                if (jp.getText().length() == 0) {
                    return null;
                }
            }
            if (!ctxt.isEnabled(.)) {
                throw ctxt.mappingException();
            }
            byte value;
            JsonToken t = jp.getCurrentToken();
            if (t == . || t == .) {
                // should we catch overflow exceptions?
                value = jp.getByteValue();
            } else {
                // [JACKSON-79]: should probably accept nulls as 'false'
                if (t != .) {
                    throw ctxt.mappingException(.getComponentType());
                }
                value = (byte) 0;
            }
            return new byte[] { value };
        }
    }
    final static class ShortDeser
        extends Base<short[]>
    {
        private static final long serialVersionUID = 1L;
        public ShortDeser() { super(short[].class); }
        @Override
        public short[] deserialize(JsonParser jpDeserializationContext ctxt)
            throws IOExceptionJsonProcessingException
        {
            if (!jp.isExpectedStartArrayToken()) {
                return handleNonArray(jpctxt);
            }
            ArrayBuilders.ShortBuilder builder = ctxt.getArrayBuilders().getShortBuilder();
            short[] chunk = builder.resetAndStart();
            int ix = 0;
            while (jp.nextToken() != .) {
                short value = _parseShortPrimitive(jpctxt);
                if (ix >= chunk.length) {
                    chunk = builder.appendCompletedChunk(chunkix);
                    ix = 0;
                }
                chunk[ix++] = value;
            }
            return builder.completeAndClearBuffer(chunkix);
        }
        private final short[] handleNonArray(JsonParser jpDeserializationContext ctxt)
            throws IOExceptionJsonProcessingException
        {
            // [JACKSON-620] Empty String can become null...
            if ((jp.getCurrentToken() == .)
                    && ctxt.isEnabled(.)) {
                if (jp.getText().length() == 0) {
                    return null;
                }
            }
            if (!ctxt.isEnabled(.)) {
                throw ctxt.mappingException();
            }
            return new short[] { _parseShortPrimitive(jpctxt) };
        }
    }
    final static class IntDeser
        extends Base<int[]>
    {
        private static final long serialVersionUID = 1L;
        public IntDeser() { super(int[].class); }
        @Override
        public int[] deserialize(JsonParser jpDeserializationContext ctxt)
            throws IOExceptionJsonProcessingException
        {
            if (!jp.isExpectedStartArrayToken()) {
                return handleNonArray(jpctxt);
            }
            ArrayBuilders.IntBuilder builder = ctxt.getArrayBuilders().getIntBuilder();
            int[] chunk = builder.resetAndStart();
            int ix = 0;
            while (jp.nextToken() != .) {
                // whether we should allow truncating conversions?
                int value = _parseIntPrimitive(jpctxt);
                if (ix >= chunk.length) {
                    chunk = builder.appendCompletedChunk(chunkix);
                    ix = 0;
                }
                chunk[ix++] = value;
            }
            return builder.completeAndClearBuffer(chunkix);
        }
        private final int[] handleNonArray(JsonParser jpDeserializationContext ctxt)
            throws IOExceptionJsonProcessingException
        {
            // [JACKSON-620] Empty String can become null...
            if ((jp.getCurrentToken() == .)
                    && ctxt.isEnabled(.)) {
                if (jp.getText().length() == 0) {
                    return null;
                }
            }
            if (!ctxt.isEnabled(.)) {
                throw ctxt.mappingException();
            }
            return new int[] { _parseIntPrimitive(jpctxt) };
        }
    }
    final static class LongDeser
        extends Base<long[]>
    {
        private static final long serialVersionUID = 1L;
        public LongDeser() { super(long[].class); }
        @Override
        public long[] deserialize(JsonParser jpDeserializationContext ctxt)
            throws IOExceptionJsonProcessingException
        {
            if (!jp.isExpectedStartArrayToken()) {
                return handleNonArray(jpctxt);
            }
            ArrayBuilders.LongBuilder builder = ctxt.getArrayBuilders().getLongBuilder();
            long[] chunk = builder.resetAndStart();
            int ix = 0;
            while (jp.nextToken() != .) {
                long value = _parseLongPrimitive(jpctxt);
                if (ix >= chunk.length) {
                    chunk = builder.appendCompletedChunk(chunkix);
                    ix = 0;
                }
                chunk[ix++] = value;
            }
            return builder.completeAndClearBuffer(chunkix);
        }
        private final long[] handleNonArray(JsonParser jpDeserializationContext ctxt)
            throws IOExceptionJsonProcessingException
        {
            // [JACKSON-620] Empty String can become null...
            if ((jp.getCurrentToken() == .)
                    && ctxt.isEnabled(.)) {
                if (jp.getText().length() == 0) {
                    return null;
                }
            }
            if (!ctxt.isEnabled(.)) {
                throw ctxt.mappingException();
            }
            return new long[] { _parseLongPrimitive(jpctxt) };
        }
    }
    final static class FloatDeser
        extends Base<float[]>
    {
        private static final long serialVersionUID = 1L;
        public FloatDeser() { super(float[].class); }
        @Override
        public float[] deserialize(JsonParser jpDeserializationContext ctxt)
            throws IOExceptionJsonProcessingException
        {
            if (!jp.isExpectedStartArrayToken()) {
                return handleNonArray(jpctxt);
            }
            ArrayBuilders.FloatBuilder builder = ctxt.getArrayBuilders().getFloatBuilder();
            float[] chunk = builder.resetAndStart();
            int ix = 0;
            while (jp.nextToken() != .) {
                // whether we should allow truncating conversions?
                float value = _parseFloatPrimitive(jpctxt);
                if (ix >= chunk.length) {
                    chunk = builder.appendCompletedChunk(chunkix);
                    ix = 0;
                }
                chunk[ix++] = value;
            }
            return builder.completeAndClearBuffer(chunkix);
        }
        private final float[] handleNonArray(JsonParser jpDeserializationContext ctxt)
            throws IOExceptionJsonProcessingException
        {
            // [JACKSON-620] Empty String can become null...
            if ((jp.getCurrentToken() == .)
                    && ctxt.isEnabled(.)) {
                if (jp.getText().length() == 0) {
                    return null;
                }
            }
            if (!ctxt.isEnabled(.)) {
                throw ctxt.mappingException();
            }
            return new float[] { _parseFloatPrimitive(jpctxt) };
        }
    }
    final static class DoubleDeser
        extends Base<double[]>
    {
        private static final long serialVersionUID = 1L;
        
        public DoubleDeser() { super(double[].class); }
        @Override
        public double[] deserialize(JsonParser jpDeserializationContext ctxt)
            throws IOExceptionJsonProcessingException
        {
            if (!jp.isExpectedStartArrayToken()) {
                return handleNonArray(jpctxt);
            }
            ArrayBuilders.DoubleBuilder builder = ctxt.getArrayBuilders().getDoubleBuilder();
            double[] chunk = builder.resetAndStart();
            int ix = 0;
            while (jp.nextToken() != .) {
                double value = _parseDoublePrimitive(jpctxt);
                if (ix >= chunk.length) {
                    chunk = builder.appendCompletedChunk(chunkix);
                    ix = 0;
                }
                chunk[ix++] = value;
            }
            return builder.completeAndClearBuffer(chunkix);
        }
        private final double[] handleNonArray(JsonParser jpDeserializationContext ctxt)
            throws IOExceptionJsonProcessingException
        {
            // [JACKSON-620] Empty String can become null...
            if ((jp.getCurrentToken() == .)
                    && ctxt.isEnabled(.)) {
                if (jp.getText().length() == 0) {
                    return null;
                }
            }
            if (!ctxt.isEnabled(.)) {
                throw ctxt.mappingException();
            }
            return new double[] { _parseDoublePrimitive(jpctxt) };
        }
    }