All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.fasterxml.jackson.databind.deser.std.JdkDeserializers Maven / Gradle / Ivy

There is a newer version: 2.17.0
Show newest version
package com.fasterxml.jackson.databind.deser.std;

import java.io.*;
import java.net.InetAddress;
import java.net.URI;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.regex.Pattern;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.deser.ContextualDeserializer;

@SuppressWarnings("serial")
public class JdkDeserializers
{
    public static StdDeserializer[] all()
    {
        return new StdDeserializer[] {

            // from String types:
            new StringDeserializer(),
            new UUIDDeserializer(),
            new URLDeserializer(),
            new URIDeserializer(),
            new FileDeserializer(),
            new CurrencyDeserializer(),
            new PatternDeserializer(),
            new LocaleDeserializer(),
            new InetAddressDeserializer(),
            new CharsetDeserializer(),

            // other types:

            // (note: AtomicInteger/Long work due to single-arg constructor;
            new AtomicBooleanDeserializer(),
            new ClassDeserializer(),
            new StackTraceElementDeserializer()
        };
    }
    
    /*
    /**********************************************************
    /* Deserializer implementations: from-String deserializers
    /**********************************************************
     */
    
    public static class UUIDDeserializer
        extends FromStringDeserializer
    {
        public UUIDDeserializer() { super(UUID.class); }

        @Override
        protected UUID _deserialize(String value, DeserializationContext ctxt)
            throws IOException, JsonProcessingException
        {
            return UUID.fromString(value);
        }
    
        @Override
        protected UUID _deserializeEmbedded(Object ob, DeserializationContext ctxt)
            throws IOException, JsonProcessingException
        {
            if (ob instanceof byte[]) {
                byte[] bytes = (byte[]) ob;
                if (bytes.length != 16) {
                    ctxt.mappingException("Can only construct UUIDs from 16 byte arrays; got "+bytes.length+" bytes");
                }
                // clumsy, but should work for now...
                DataInputStream in = new DataInputStream(new ByteArrayInputStream(bytes));
                long l1 = in.readLong();
                long l2 = in.readLong();
                return new UUID(l1, l2);
            }
            super._deserializeEmbedded(ob, ctxt);
            return null; // never gets here
        }
    }

    public static class URLDeserializer
        extends FromStringDeserializer
    {
        public URLDeserializer() { super(URL.class); }
        
        @Override
        protected URL _deserialize(String value, DeserializationContext ctxt)
            throws IOException
        {
            return new URL(value);
        }
    }
    
    public static class URIDeserializer
        extends FromStringDeserializer
    {
        public URIDeserializer() { super(URI.class); }
    
        @Override
        protected URI _deserialize(String value, DeserializationContext ctxt)
            throws IllegalArgumentException
        {
            return URI.create(value);
        }
    }
    
    public static class CurrencyDeserializer
        extends FromStringDeserializer
    {
        public CurrencyDeserializer() { super(Currency.class); }
        
        @Override
        protected Currency _deserialize(String value, DeserializationContext ctxt)
            throws IllegalArgumentException
        {
            // will throw IAE if unknown:
            return Currency.getInstance(value);
        }
    }
    
    public static class PatternDeserializer
        extends FromStringDeserializer
    {
        public PatternDeserializer() { super(Pattern.class); }
        
        @Override
        protected Pattern _deserialize(String value, DeserializationContext ctxt)
            throws IllegalArgumentException
        {
            // will throw IAE (or its subclass) if malformed
            return Pattern.compile(value);
        }
    }
    
    /**
     * Kept protected as it's not meant to be extensible at this point
     */
    protected static class LocaleDeserializer
        extends FromStringDeserializer
    {
        public LocaleDeserializer() { super(Locale.class); }
        
        @Override
        protected Locale _deserialize(String value, DeserializationContext ctxt)
            throws IOException
        {
            int ix = value.indexOf('_');
            if (ix < 0) { // single argument
                return new Locale(value);
            }
            String first = value.substring(0, ix);
            value = value.substring(ix+1);
            ix = value.indexOf('_');
            if (ix < 0) { // two pieces
                return new Locale(first, value);
            }
            String second = value.substring(0, ix);
            return new Locale(first, second, value.substring(ix+1));
        }
    }
    
    /**
     * As per [JACKSON-484], also need special handling for InetAddress...
     */
    protected static class InetAddressDeserializer
        extends FromStringDeserializer
    {
        public InetAddressDeserializer() { super(InetAddress.class); }
    
        @Override
        protected InetAddress _deserialize(String value, DeserializationContext ctxt)
            throws IOException
        {
            return InetAddress.getByName(value);
        }
    }

    // [JACKSON-789]
    protected static class CharsetDeserializer
        extends FromStringDeserializer
    {
        public CharsetDeserializer() { super(Charset.class); }
    
        @Override
        protected Charset _deserialize(String value, DeserializationContext ctxt)
            throws IOException
        {
            return Charset.forName(value);
        }
    }

    public static class FileDeserializer
        extends FromStringDeserializer
    {
        public FileDeserializer() { super(File.class); }
        
        @Override
        protected File _deserialize(String value, DeserializationContext ctxt)
        {
            return new File(value);
        }
    }
    
    /*
    /**********************************************************
    /* AtomicXxx types
    /**********************************************************
     */
    
    public static class AtomicReferenceDeserializer
        extends StdScalarDeserializer>
        implements ContextualDeserializer
    {
        /**
         * Type of value that we reference
         */
        protected final JavaType _referencedType;
        
        protected final JsonDeserializer _valueDeserializer;
        
        /**
         * @param referencedType Parameterization of this reference
         */
        public AtomicReferenceDeserializer(JavaType referencedType) {
            this(referencedType, null);
        }
        
        public AtomicReferenceDeserializer(JavaType referencedType,
                JsonDeserializer deser)
        {
            super(AtomicReference.class);
            _referencedType = referencedType;
            _valueDeserializer = deser;
        }
        
        @Override
        public AtomicReference deserialize(JsonParser jp, DeserializationContext ctxt)
            throws IOException, JsonProcessingException
        {
            return new AtomicReference(_valueDeserializer.deserialize(jp, ctxt));
        }
        
//        @Override
        public JsonDeserializer createContextual(DeserializationContext ctxt,
                BeanProperty property) throws JsonMappingException
        {
            JsonDeserializer deser = _valueDeserializer;
            if (deser != null) {
                return this;
            }
            return new AtomicReferenceDeserializer(_referencedType,
                    ctxt.findContextualValueDeserializer(_referencedType, property));
        }
    }

    public static class AtomicBooleanDeserializer
        extends StdScalarDeserializer
    {
        public AtomicBooleanDeserializer() { super(AtomicBoolean.class); }
        
        @Override
        public AtomicBoolean deserialize(JsonParser jp, DeserializationContext ctxt)
            throws IOException, JsonProcessingException
        {
            // 16-Dec-2010, tatu: Should we actually convert null to null AtomicBoolean?
            return new AtomicBoolean(_parseBooleanPrimitive(jp, ctxt));
        }
    }
    
    /*
    /**********************************************************
    /* Deserializers for other JDK types
    /**********************************************************
     */

    public static class StackTraceElementDeserializer
        extends StdScalarDeserializer
    {
        public StackTraceElementDeserializer() { super(StackTraceElement.class); }
    
        @Override
        public StackTraceElement deserialize(JsonParser jp, DeserializationContext ctxt)
            throws IOException, JsonProcessingException
        {
            JsonToken t = jp.getCurrentToken();
            // Must get an Object
            if (t == JsonToken.START_OBJECT) {
                String className = "", methodName = "", fileName = "";
                int lineNumber = -1;
    
                while ((t = jp.nextValue()) != JsonToken.END_OBJECT) {
                    String propName = jp.getCurrentName();
                    if ("className".equals(propName)) {
                        className = jp.getText();
                    } else if ("fileName".equals(propName)) {
                        fileName = jp.getText();
                    } else if ("lineNumber".equals(propName)) {
                        if (t.isNumeric()) {
                            lineNumber = jp.getIntValue();
                        } else {
                            throw JsonMappingException.from(jp, "Non-numeric token ("+t+") for property 'lineNumber'");
                        }
                    } else if ("methodName".equals(propName)) {
                        methodName = jp.getText();
                    } else if ("nativeMethod".equals(propName)) {
                        // no setter, not passed via constructor: ignore
                    } else {
                        handleUnknownProperty(jp, ctxt, _valueClass, propName);
                    }
                }
                return new StackTraceElement(className, methodName, fileName, lineNumber);
            }
            throw ctxt.mappingException(_valueClass, t);
        }
    }
}