Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  package com.fasterxml.jackson.databind.deser.std;
  
  import java.util.*;
  
Basic serializer that can take Json "Object" structure and construct a java.util.Map instance, with typed contents.

Note: for untyped content (one indicated by passing Object.class as the type), UntypedObjectDeserializer is used instead. It can also construct java.util.Maps, but not with specific POJO types, only other containers and primitives/wrappers.

 
 public class MapDeserializer
 {
     private static final long serialVersionUID = -3378654289961736240L;
 
     // // Configuration: typing, deserializers
 
     protected final JavaType _mapType;

    
Key deserializer to use; either passed via constructor (when indicated by annotations), or resolved when resolve(com.fasterxml.jackson.databind.DeserializationContext) is called;
 
     protected final KeyDeserializer _keyDeserializer;

    
Flag set to indicate that the key type is java.lang.String (or java.lang.Object, for which String is acceptable), and that the default Jackson key deserializer would be used. If both are true, can optimize handling.
 
     protected boolean _standardStringKey;

    
Value deserializer.
 
     protected final JsonDeserializer<Object_valueDeserializer;

    
If value instances have polymorphic type information, this is the type deserializer that can handle it
 
     protected final TypeDeserializer _valueTypeDeserializer;
     
     // // Instance construction settings:
 
     protected final ValueInstantiator _valueInstantiator;
 
     protected final boolean _hasDefaultCreator;

    
Deserializer that is used iff delegate-based creator is to be used for deserializing from JSON Object.
 
     protected JsonDeserializer<Object_delegateDeserializer;

    
If the Map is to be instantiated using non-default constructor or factory method that takes one or more named properties as argument(s), this creator is used for instantiation.
 
     protected PropertyBasedCreator _propertyBasedCreator;    
 
     // // Any properties to ignore if seen?
     
     protected HashSet<String_ignorableProperties;
 
     /*
     /**********************************************************
     /* Life-cycle
     /**********************************************************
      */
 
     public MapDeserializer(JavaType mapTypeValueInstantiator valueInstantiator,
             KeyDeserializer keyDeserJsonDeserializer<ObjectvalueDeser,
             TypeDeserializer valueTypeDeser)
     {
         super(mapType);
          = mapType;
         = keyDeser;
         = valueDeser;
         = valueTypeDeser;
         = valueInstantiator;
         = valueInstantiator.canCreateUsingDefault();
         = null;
         = null;
         = _isStdKeyDeser(mapTypekeyDeser);
    }

    
Copy-constructor that can be used by sub-classes to allow copy-on-write styling copying of settings of an existing instance.
    protected MapDeserializer(MapDeserializer src)
    {
        super(src._mapType);
         = src._mapType;
         = src._keyDeserializer;
         = src._valueDeserializer;
         = src._valueTypeDeserializer;
         = src._valueInstantiator;
         = src._propertyBasedCreator;
         = src._delegateDeserializer;
         = src._hasDefaultCreator;
        // should we make a copy here?
         = src._ignorableProperties;
         = src._standardStringKey;
    }
    protected MapDeserializer(MapDeserializer src,
            KeyDeserializer keyDeserJsonDeserializer<ObjectvalueDeser,
            TypeDeserializer valueTypeDeser,
            HashSet<Stringignorable)
    {
        super(src._mapType);
         = src._mapType;
         = keyDeser;
         = valueDeser;
         = valueTypeDeser;
         = src._valueInstantiator;
         = src._propertyBasedCreator;
         = src._delegateDeserializer;
         = src._hasDefaultCreator;
         = ignorable;
         = _isStdKeyDeser(keyDeser);
    }

    
Fluent factory method used to create a copy with slightly different settings. When sub-classing, MUST be overridden.
    @SuppressWarnings("unchecked")
    protected MapDeserializer withResolved(KeyDeserializer keyDeser,
            TypeDeserializer valueTypeDeserJsonDeserializer<?> valueDeser,
            HashSet<Stringignorable)
    {
        
        if (( == keyDeser) && ( == valueDeser) && ( == valueTypeDeser)
                && ( == ignorable)) {
            return this;
        }
        return new MapDeserializer(this,
                keyDeser, (JsonDeserializer<Object>) valueDeservalueTypeDeserignorable);
    }

    
Helper method used to check whether we can just use the default key deserialization, where JSON String becomes Java String.
    protected final boolean _isStdKeyDeser(JavaType mapTypeKeyDeserializer keyDeser)
    {
        if (keyDeser == null) {
            return true;
        }
        JavaType keyType = mapType.getKeyType();
        if (keyType == null) { // assumed to be Object
            return true;
        }
        Class<?> rawKeyType = keyType.getRawClass();
        return ((rawKeyType == String.class || rawKeyType == Object.class)
                && isDefaultKeyDeserializer(keyDeser));
    }
    
    public void setIgnorableProperties(String[] ignorable)
    {
         = (ignorable == null || ignorable.length == 0) ?
            null : ArrayBuilders.arrayToSet(ignorable);
    }
    /*
    /**********************************************************
    /* Validation, post-processing (ResolvableDeserializer)
    /**********************************************************
     */
    @Override
    public void resolve(DeserializationContext ctxtthrows JsonMappingException
    {
        // May need to resolve types for delegate- and/or property-based creators:
            JavaType delegateType = .getDelegateType(ctxt.getConfig());
            if (delegateType == null) {
                throw new IllegalArgumentException("Invalid delegate-creator definition for "+
                        +": value instantiator ("+.getClass().getName()
                        +") returned true for 'canCreateUsingDelegate()', but null for 'getDelegateType()'");
            }
            /* Theoretically should be able to get CreatorProperty for delegate
             * parameter to pass; but things get tricky because DelegateCreator
             * may contain injectable values. So, for now, let's pass nothing.
             */
             = findDeserializer(ctxtdelegateTypenull);
        }
            SettableBeanProperty[] creatorProps = .getFromObjectArguments(ctxt.getConfig());
             = PropertyBasedCreator.construct(ctxtcreatorProps);
        }
    }

    
Method called to finalize setup of this deserializer, when it is known for which property deserializer is needed for.
    @Override
            BeanProperty propertythrows JsonMappingException
    {
        KeyDeserializer kd = ;
        if (kd == null) {
            kd = ctxt.findKeyDeserializer(.getKeyType(), property);
        } else {
            if (kd instanceof ContextualKeyDeserializer) {
                kd = ((ContextualKeyDeserializerkd).createContextual(ctxtproperty);
            }
        }
        JsonDeserializer<?> vd = ;
        // #125: May have a content converter
        vd = findConvertingContentDeserializer(ctxtpropertyvd);
        if (vd == null) {
            vd = ctxt.findContextualValueDeserializer(.getContentType(), property);
        } else { // if directly assigned, probably not yet contextual, so:
            vd = ctxt.handleSecondaryContextualization(vdproperty);
        }
        if (vtd != null) {
            vtd = vtd.forProperty(property);
        }
        HashSet<Stringignored = ;
        AnnotationIntrospector intr = ctxt.getAnnotationIntrospector();
        if (intr != null && property != null) {
            String[] moreToIgnore = intr.findPropertiesToIgnore(property.getMember());
            if (moreToIgnore != null) {
                ignored = (ignored == null) ? new HashSet<String>() : new HashSet<String>(ignored);
                for (String str : moreToIgnore) {
                    ignored.add(str);
                }
            }
        }
        return withResolved(kdvtdvdignored);
    }
    
    /*
    /**********************************************************
    /* ContainerDeserializerBase API
    /**********************************************************
     */
    @Override
    public JavaType getContentType() {
        return .getContentType();
    }
    @Override
        return ;
    }
    
    /*
    /**********************************************************
    /* JsonDeserializer API
    /**********************************************************
     */
    @Override
    @SuppressWarnings("unchecked")
        throws IOExceptionJsonProcessingException
    {
        if ( != null) {
            return _deserializeUsingCreator(jpctxt);
        }
        if ( != null) {
            return (Map<Object,Object>) .createUsingDelegate(ctxt,
                    .deserialize(jpctxt));
        }
        if (!) {
            throw ctxt.instantiationException(getMapClass(), "No default constructor found");
        }
        // Ok: must point to START_OBJECT, FIELD_NAME or END_OBJECT
        JsonToken t = jp.getCurrentToken();
        if (t != . && t != . && t != .) {
            // [JACKSON-620] (empty) String may be ok however:
            if (t == .) {
                return (Map<Object,Object>) .createFromString(ctxtjp.getText());
            }
            throw ctxt.mappingException(getMapClass());
        }
        final Map<Object,Objectresult = (Map<Object,Object>) .createUsingDefault(ctxt);
        if () {
            _readAndBindStringMap(jpctxtresult);
            return result;
        }
        _readAndBind(jpctxtresult);
        return result;
    }
    @Override
            Map<Object,Objectresult)
        throws IOExceptionJsonProcessingException
    {
        // Ok: must point to START_OBJECT or FIELD_NAME
        JsonToken t = jp.getCurrentToken();
        if (t != . && t != .) {
            throw ctxt.mappingException(getMapClass());
        }
        if () {
            _readAndBindStringMap(jpctxtresult);
            return result;
        }
        _readAndBind(jpctxtresult);
        return result;
    }
    @Override
            TypeDeserializer typeDeserializer)
        throws IOExceptionJsonProcessingException
    {
        // In future could check current token... for now this should be enough:
        return typeDeserializer.deserializeTypedFromObject(jpctxt);
    }
    
    /*
    /**********************************************************
    /* Other public accessors
    /**********************************************************
     */
    @SuppressWarnings("unchecked")
    public final Class<?> getMapClass() { return (Class<Map<Object,Object>>) .getRawClass(); }
    @Override public JavaType getValueType() { return ; }
    /*
    /**********************************************************
    /* Internal methods
    /**********************************************************
     */
    protected final void _readAndBind(JsonParser jpDeserializationContext ctxt,
            Map<Object,Objectresult)
        throws IOExceptionJsonProcessingException
    {
        JsonToken t = jp.getCurrentToken();
        if (t == .) {
            t = jp.nextToken();
        }
        final KeyDeserializer keyDes = ;
        final JsonDeserializer<ObjectvalueDes = ;
        final TypeDeserializer typeDeser = ;
        for (; t == .t = jp.nextToken()) {
            // Must point to field name
            String fieldName = jp.getCurrentName();
            Object key = keyDes.deserializeKey(fieldNamectxt);
            // And then the value...
            t = jp.nextToken();
            if ( != null && .contains(fieldName)) {
                jp.skipChildren();
                continue;
            }
            // Note: must handle null explicitly here; value deserializers won't
            Object value;            
            if (t == .) {
                value = null;
            } else if (typeDeser == null) {
                value = valueDes.deserialize(jpctxt);
            } else {
                value = valueDes.deserializeWithType(jpctxttypeDeser);
            }
            /* !!! 23-Dec-2008, tatu: should there be an option to verify
             *   that there are no duplicate field names? (and/or what
             *   to do, keep-first or keep-last)
             */
            result.put(keyvalue);
        }
    }

    
Optimized method used when keys can be deserialized as plain old java.lang.Strings, and there is no custom deserialized specified.
    protected final void _readAndBindStringMap(JsonParser jpDeserializationContext ctxt,
            Map<Object,Objectresult)
        throws IOExceptionJsonProcessingException
    {
        JsonToken t = jp.getCurrentToken();
        if (t == .) {
            t = jp.nextToken();
        }
        final JsonDeserializer<ObjectvalueDes = ;
        final TypeDeserializer typeDeser = ;
        for (; t == .t = jp.nextToken()) {
            // Must point to field name
            String fieldName = jp.getCurrentName();
            // And then the value...
            t = jp.nextToken();
            if ( != null && .contains(fieldName)) {
                jp.skipChildren();
                continue;
            }
            // Note: must handle null explicitly here; value deserializers won't
            Object value;            
            if (t == .) {
                value = null;
            } else if (typeDeser == null) {
                value = valueDes.deserialize(jpctxt);
            } else {
                value = valueDes.deserializeWithType(jpctxttypeDeser);
            }
            result.put(fieldNamevalue);
        }
    }
    
    @SuppressWarnings("unchecked"
        throws IOExceptionJsonProcessingException
    {
        final PropertyBasedCreator creator = ;
        // null -> no ObjectIdReader for Maps (yet?)
        PropertyValueBuffer buffer = creator.startBuilding(jpctxtnull);
        JsonToken t = jp.getCurrentToken();
        if (t == .) {
            t = jp.nextToken();
        }
        final JsonDeserializer<ObjectvalueDes = ;
        final TypeDeserializer typeDeser = ;
        for (; t == .t = jp.nextToken()) {
            String propName = jp.getCurrentName();
            t = jp.nextToken(); // to get to value
            if ( != null && .contains(propName)) {
                jp.skipChildren(); // and skip it (in case of array/object)
                continue;
            }
            // creator property?
            SettableBeanProperty prop = creator.findCreatorProperty(propName);
            if (prop != null) {
                // Last property to set?
                Object value = prop.deserialize(jpctxt);
                if (buffer.assignParameter(prop.getCreatorIndex(), value)) {
                    jp.nextToken();
                    Map<Object,Objectresult;
                    try {
                        result = (Map<Object,Object>)creator.build(ctxtbuffer);
                    } catch (Exception e) {
                        wrapAndThrow(e.getRawClass());
                        return null;
                    }
                    _readAndBind(jpctxtresult);
                    return result;
                }
                continue;
            }
            // other property? needs buffering
            String fieldName = jp.getCurrentName();
            Object key = .deserializeKey(fieldNamectxt);
            Object value;            
            if (t == .) {
                value = null;
            } else if (typeDeser == null) {
                value = valueDes.deserialize(jpctxt);
            } else {
                value = valueDes.deserializeWithType(jpctxttypeDeser);
            }
            buffer.bufferMapProperty(keyvalue);
        }
        // end of JSON object?
        // if so, can just construct and leave...
        try {
            return (Map<Object,Object>)creator.build(ctxtbuffer);
        } catch (Exception e) {
            wrapAndThrow(e.getRawClass());
            return null;
        }
    }
    // note: copied form BeanDeserializer; should try to share somehow...
    protected void wrapAndThrow(Throwable tObject ref)
        throws IOException
    {
        // to handle StackOverflow:
        while (t instanceof InvocationTargetException && t.getCause() != null) {
            t = t.getCause();
        }
        // Errors and "plain" IOExceptions to be passed as is
        if (t instanceof Error) {
            throw (Errort;
        }
        // ... except for mapping exceptions
        if (t instanceof IOException && !(t instanceof JsonMappingException)) {
            throw (IOExceptiont;
        }
        throw JsonMappingException.wrapWithPath(trefnull);
    }
New to GrepCode? Check out our FAQ X