Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  package com.fasterxml.jackson.databind.deser;
  
  import java.util.*;
  
Class that handles deserialization using a separate Builder class, which is used for data binding and produces actual deserialized value at the end of data binding.

Note on implementation: much of code has been copied from BeanDeserializer; there may be opportunities to refactor this in future.

 
     extends BeanDeserializerBase
 {
     private static final long serialVersionUID = 1L;
 
     protected final AnnotatedMethod _buildMethod;
 	
     /*
     /**********************************************************
     /* Life-cycle, construction, initialization
     /**********************************************************
      */

    
Constructor used by BeanDeserializerBuilder.
 
             BeanDescription beanDesc,
             BeanPropertyMap propertiesMap<StringSettableBeanPropertybackRefs,
             HashSet<StringignorablePropsboolean ignoreAllUnknown,
             boolean hasViews)
     {
     	super(builderbeanDescpropertiesbackRefs,
     			ignorablePropsignoreAllUnknownhasViews);
     	 = builder.getBuildMethod();
     	// 05-Mar-2012, tatu: Can not really make Object Ids work with builders, not yet anyway
     	if ( != null) {
     	    throw new IllegalArgumentException("Can not use Object Id with Builder-based deserialization (type "
     	            +beanDesc.getType()+")");
     	}
     }

    
Copy-constructor that can be used by sub-classes to allow copy-on-write styling copying of settings of an existing instance.
 
     {
         this(srcsrc._ignoreAllUnknown);
     }
 
     protected BuilderBasedDeserializer(BuilderBasedDeserializer srcboolean ignoreAllUnknown)
     {
         super(srcignoreAllUnknown);
          = src._buildMethod;
     }
     
     protected BuilderBasedDeserializer(BuilderBasedDeserializer srcNameTransformer unwrapper) {
     	super(srcunwrapper);
          = src._buildMethod;
     }
 
         super(srcoir);
          = src._buildMethod;
     }
 
     public BuilderBasedDeserializer(BuilderBasedDeserializer srcHashSet<StringignorableProps) {
         super(srcignorableProps);
          = src._buildMethod;
     }
     
     @Override
     {
         /* main thing really is to just enforce ignoring of unknown
          * properties; since there may be multiple unwrapped values
          * and properties for all may be interleaved...
          */
         return new BuilderBasedDeserializer(thisunwrapper);
     }
 
     @Override
         return new BuilderBasedDeserializer(thisoir);
     }
 
    @Override
        return new BuilderBasedDeserializer(thisignorableProps);
    }
    @Override
        return new BeanAsArrayBuilderDeserializer(thisprops);
    }
    
    /*
    /**********************************************************
    /* JsonDeserializer implementation
    /**********************************************************
     */
    
    protected final Object finishBuild(DeserializationContext ctxtObject builder)
            throws IOException
    {
        try {
            return .getMember().invoke(builder);
    	} catch (Exception e) {
    	    wrapInstantiationProblem(ectxt);
    	    return null;
    	}
    }
    
    
Main deserialization method for bean-based objects (POJOs).
    @Override
    public final Object deserialize(JsonParser jpDeserializationContext ctxt)
        throws IOExceptionJsonProcessingException
    {
        JsonToken t = jp.getCurrentToken();
        
        // common case first:
        if (t == .) {
            t = jp.nextToken();
            if () {
            	return finishBuild(ctxtvanillaDeserialize(jpctxtt));
            }
            Object builder = deserializeFromObject(jpctxt);
            return finishBuild(ctxtbuilder);
        }
        // and then others, generally requiring use of @JsonCreator
        switch (t) {
        case :
            return finishBuild(ctxtdeserializeFromString(jpctxt));
        case :
            return finishBuild(ctxtdeserializeFromNumber(jpctxt));
        case :
        	return finishBuild(ctxtdeserializeFromDouble(jpctxt));
        case :
            return jp.getEmbeddedObject();
        case :
        case :
            return finishBuild(ctxtdeserializeFromBoolean(jpctxt));
        case :
            // these only work if there's a (delegating) creator...
            return finishBuild(ctxtdeserializeFromArray(jpctxt));
        case :
        case // added to resolve [JACKSON-319], possible related issues
            return finishBuild(ctxtdeserializeFromObject(jpctxt));
        default:
            throw ctxt.mappingException(getBeanClass());
        }
    }

    
Secondary deserialization method, called in cases where POJO instance is created as part of deserialization, potentially after collecting some or all of the properties to set.
    @Override
    		Object builder)
        throws IOExceptionJsonProcessingException
    {
        /* Important: we call separate method which does NOT call
         * 'finishBuild()', to avoid problems with recursion
         */
        return finishBuild(ctxt_deserialize(jpctxtbuilder));
    }
    
    /*
    /**********************************************************
    /* Concrete deserialization methods
    /**********************************************************
     */
    protected final Object _deserialize(JsonParser jp,
            DeserializationContext ctxtObject builder)
        throws IOExceptionJsonProcessingException
    {        
        if ( != null) {
            injectValues(ctxtbuilder);
        }
        if ( != null) {
            return deserializeWithUnwrapped(jpctxtbuilder);
        }
        if ( != null) {
            return deserializeWithExternalTypeId(jpctxtbuilder);
        }
        if () {
            Class<?> view = ctxt.getActiveView();
            if (view != null) {
                return deserializeWithView(jpctxtbuilderview);
            }
        }
        JsonToken t = jp.getCurrentToken();
        // 23-Mar-2010, tatu: In some cases, we start with full JSON object too...
        if (t == .) {
            t = jp.nextToken();
        }
        for (; t == .t = jp.nextToken()) {
            String propName = jp.getCurrentName();
            // Skip field name:
            jp.nextToken();
            SettableBeanProperty prop = .find(propName);
            
            if (prop != null) { // normal case
                try {
                    builder = prop.deserializeSetAndReturn(jpctxtbuilder);
                } catch (Exception e) {
                    wrapAndThrow(ebuilderpropNamectxt);
                }
                continue;
            }
            if ( != null && .contains(propName)) {
                jp.skipChildren();
            } else if ( != null) {
                // should we try to get return value of any setter too?
                .deserializeAndSet(jpctxtbuilderpropName);
                continue;
            } else {
                // Unknown: let's call handler method
                handleUnknownProperty(jpctxtbuilderpropName);
            }
        }
        return builder;
    }
    
    
Streamlined version that is only used when no "special" features are enabled.
    private final Object vanillaDeserialize(JsonParser jp,
        throws IOExceptionJsonProcessingException
    {
        Object bean = .createUsingDefault(ctxt);
        for (; jp.getCurrentToken() != .jp.nextToken()) {
            String propName = jp.getCurrentName();
            // Skip field name:
            jp.nextToken();
            SettableBeanProperty prop = .find(propName);
            if (prop != null) { // normal case
                try {
                    bean = prop.deserializeSetAndReturn(jpctxtbean);
                } catch (Exception e) {
                    wrapAndThrow(ebeanpropNamectxt);
                }
            } else {
                handleUnknownVanilla(jpctxtbeanpropName);
            }
        }
        return bean;
    }

    
General version used when handling needs more advanced features.
    @Override
        throws IOExceptionJsonProcessingException
    {
        if () {
            if ( != null) {
                return deserializeWithUnwrapped(jpctxt);
            }
            if ( != null) {
                return deserializeWithExternalTypeId(jpctxt);
            }
            return deserializeFromObjectUsingNonDefault(jpctxt);
        }
        Object bean = .createUsingDefault(ctxt);
        if ( != null) {
            injectValues(ctxtbean);
        }
        if () {
            Class<?> view = ctxt.getActiveView();
            if (view != null) {
                return deserializeWithView(jpctxtbeanview);
            }
        }
        for (; jp.getCurrentToken() != .jp.nextToken()) {
            String propName = jp.getCurrentName();
            // Skip field name:
            jp.nextToken();
            SettableBeanProperty prop = .find(propName);
            if (prop != null) { // normal case
                try {
                    bean = prop.deserializeSetAndReturn(jpctxtbean);
                } catch (Exception e) {
                    wrapAndThrow(ebeanpropNamectxt);
                }
                continue;
            }
            /* As per [JACKSON-313], things marked as ignorable should not be
             * passed to any setter
             */
            if ( != null && .contains(propName)) {
                jp.skipChildren();
            } else if ( != null) {
                try {
                    .deserializeAndSet(jpctxtbeanpropName);
                } catch (Exception e) {
                    wrapAndThrow(ebeanpropNamectxt);
                }
                continue;
            } else {
                // Unknown: let's call handler method
                handleUnknownProperty(jpctxtbeanpropName);         
            }
        }
        return bean;
    }

    
Method called to deserialize bean using "property-based creator": this means that a non-default constructor or factory method is called, and then possibly other setters. The trick is that values for creator method need to be buffered, first; and due to non-guaranteed ordering possibly some other properties as well.
    @Override
    protected final Object _deserializeUsingPropertyBased(final JsonParser jp,
            final DeserializationContext ctxt)
        throws IOExceptionJsonProcessingException
    { 
        final PropertyBasedCreator creator = ;
        PropertyValueBuffer buffer = creator.startBuilding(jpctxt);
        // 04-Jan-2010, tatu: May need to collect unknown properties for polymorphic cases
        TokenBuffer unknown = null;
        JsonToken t = jp.getCurrentToken();
        for (; t == .t = jp.nextToken()) {
            String propName = jp.getCurrentName();
            jp.nextToken(); // to point to value
            // creator property?
            SettableBeanProperty creatorProp = creator.findCreatorProperty(propName);
            if (creatorProp != null) {
                // Last creator property to set?
                Object value = creatorProp.deserialize(jpctxt);
                if (buffer.assignParameter(creatorProp.getCreatorIndex(), value)) {
                    jp.nextToken(); // to move to following FIELD_NAME/END_OBJECT
                    Object bean;
                    try {
                        bean = creator.build(ctxtbuffer);
                    } catch (Exception e) {
                        wrapAndThrow(e.getRawClass(), propNamectxt);
                        continue// never gets here
                    }
                    //  polymorphic?
                    if (bean.getClass() != .getRawClass()) {
                        return handlePolymorphic(jpctxtbeanunknown);
                    }
                    if (unknown != null) { // nope, just extra unknown stuff...
                        bean = handleUnknownProperties(ctxtbeanunknown);
                    }
                    // or just clean?
                    return _deserialize(jpctxtbean);
                }
                continue;
            }
            // Object Id property?
            if (buffer.readIdProperty(propName)) {
                continue;
            }
            // regular property? needs buffering
            SettableBeanProperty prop = .find(propName);
            if (prop != null) {
                buffer.bufferProperty(propprop.deserialize(jpctxt));
                continue;
            }
            // As per [JACKSON-313], things marked as ignorable should not be
            // passed to any setter
            if ( != null && .contains(propName)) {
                jp.skipChildren();
                continue;
            }
            // "any property"?
            if ( != null) {
                buffer.bufferAnyProperty(propName.deserialize(jpctxt));
                continue;
            }
            // Ok then, let's collect the whole field; name and value
            if (unknown == null) {
                unknown = new TokenBuffer(jp.getCodec());
            }
            unknown.writeFieldName(propName);
            unknown.copyCurrentStructure(jp);
        }
        // We hit END_OBJECT, so:
        Object bean;
        try {
            bean = creator.build(ctxtbuffer);
        } catch (Exception e) {
            wrapInstantiationProblem(ectxt);
            return null// never gets here
        }
        if (unknown != null) {
            // polymorphic?
            if (bean.getClass() != .getRawClass()) {
                return handlePolymorphic(nullctxtbeanunknown);
            }
            // no, just some extra unknown properties
            return handleUnknownProperties(ctxtbeanunknown);
        }
        return bean;
    }
    
    /*
    /**********************************************************
    /* Deserializing when we have to consider an active View
    /**********************************************************
     */
    
    protected final Object deserializeWithView(JsonParser jpDeserializationContext ctxt,
            Object beanClass<?> activeView)
        throws IOExceptionJsonProcessingException
    {
        JsonToken t = jp.getCurrentToken();
        for (; t == .t = jp.nextToken()) {
            String propName = jp.getCurrentName();
            // Skip field name:
            jp.nextToken();
            SettableBeanProperty prop = .find(propName);
            if (prop != null) {
                if (!prop.visibleInView(activeView)) {
                    jp.skipChildren();
                    continue;
                }
                try {
                    bean = prop.deserializeSetAndReturn(jpctxtbean);
                } catch (Exception e) {
                    wrapAndThrow(ebeanpropNamectxt);
                }
                continue;
            }
            /* As per [JACKSON-313], things marked as ignorable should not be
             * passed to any setter
             */
            if ( != null && .contains(propName)) {
                jp.skipChildren();
            } else if ( != null) {
                .deserializeAndSet(jpctxtbeanpropName);
                continue;
            } else {
                // Unknown: let's call handler method
                handleUnknownProperty(jpctxtbeanpropName);
            }
        }
        return bean;
    }
    
    /*
    /**********************************************************
    /* Handling for cases where we have "unwrapped" values
    /**********************************************************
     */

    
Method called when there are declared "unwrapped" properties which need special handling
        throws IOExceptionJsonProcessingException
    {
        if ( != null) {
            return .createUsingDelegate(ctxt.deserialize(jpctxt));
        }
        if ( != null) {
            return deserializeUsingPropertyBasedWithUnwrapped(jpctxt);
        }
        TokenBuffer tokens = new TokenBuffer(jp.getCodec());
        tokens.writeStartObject();
        Object bean = .createUsingDefault(ctxt);
        if ( != null) {
            injectValues(ctxtbean);
        }
        final Class<?> activeView =  ? ctxt.getActiveView() : null;
        
        for (; jp.getCurrentToken() != .jp.nextToken()) {
            String propName = jp.getCurrentName();
            jp.nextToken();
            SettableBeanProperty prop = .find(propName);
            if (prop != null) { // normal case
                if (activeView != null && !prop.visibleInView(activeView)) {
                    jp.skipChildren();
                    continue;
                }
                try {
                    bean = prop.deserializeSetAndReturn(jpctxtbean);
                } catch (Exception e) {
                    wrapAndThrow(ebeanpropNamectxt);
                }
                continue;
            }
            // ignorable things should be ignored
            if ( != null && .contains(propName)) {
                jp.skipChildren();
                continue;
            }
            // but... others should be passed to unwrapped property deserializers
            tokens.writeFieldName(propName);
            tokens.copyCurrentStructure(jp);
            // how about any setter? We'll get copies but...
            if ( != null) {
                try {
                    .deserializeAndSet(jpctxtbeanpropName);
                } catch (Exception e) {
                    wrapAndThrow(ebeanpropNamectxt);
                }
                continue;
            }
        }
        tokens.writeEndObject();
        .processUnwrapped(jpctxtbeantokens);
        return bean;
    }    
    		DeserializationContext ctxtObject bean)
        throws IOExceptionJsonProcessingException
    {
        JsonToken t = jp.getCurrentToken();
        if (t == .) {
            t = jp.nextToken();
        }
        TokenBuffer tokens = new TokenBuffer(jp.getCodec());
        tokens.writeStartObject();
        final Class<?> activeView =  ? ctxt.getActiveView() : null;
        for (; t == .t = jp.nextToken()) {
            String propName = jp.getCurrentName();
            SettableBeanProperty prop = .find(propName);
            jp.nextToken();
            if (prop != null) { // normal case
                if (activeView != null && !prop.visibleInView(activeView)) {
                    jp.skipChildren();
                    continue;
                }
                try {
                    bean = prop.deserializeSetAndReturn(jpctxtbean);
                } catch (Exception e) {
                    wrapAndThrow(ebeanpropNamectxt);
                }
                continue;
            }
            if ( != null && .contains(propName)) {
                jp.skipChildren();
                continue;
            }
            // but... others should be passed to unwrapped property deserializers
            tokens.writeFieldName(propName);
            tokens.copyCurrentStructure(jp);
            // how about any setter? We'll get copies but...
            if ( != null) {
                .deserializeAndSet(jpctxtbeanpropName);
            }
        }
        tokens.writeEndObject();
        .processUnwrapped(jpctxtbeantokens);
        return bean;
    }
    @SuppressWarnings("resource")
        throws IOExceptionJsonProcessingException
    {
        final PropertyBasedCreator creator = ;
        PropertyValueBuffer buffer = creator.startBuilding(jpctxt);
        TokenBuffer tokens = new TokenBuffer(jp.getCodec());
        tokens.writeStartObject();
        JsonToken t = jp.getCurrentToken();
        for (; t == .t = jp.nextToken()) {
            String propName = jp.getCurrentName();
            jp.nextToken(); // to point to value
            // creator property?
            SettableBeanProperty creatorProp = creator.findCreatorProperty(propName);
            if (creatorProp != null) {
                // Last creator property to set?
                Object value = creatorProp.deserialize(jpctxt);
                if (buffer.assignParameter(creatorProp.getCreatorIndex(), value)) {
                    t = jp.nextToken(); // to move to following FIELD_NAME/END_OBJECT
                    Object bean;
                    try {
                        bean = creator.build(ctxtbuffer);
                    } catch (Exception e) {
                        wrapAndThrow(e.getRawClass(), propNamectxt);
                        continue// never gets here
                    }
                    // if so, need to copy all remaining tokens into buffer
                    while (t == .) {
                        jp.nextToken(); // to skip name
                        tokens.copyCurrentStructure(jp);
                        t = jp.nextToken();
                    }
                    tokens.writeEndObject();
                    if (bean.getClass() != .getRawClass()) {
                        // !!! 08-Jul-2011, tatu: Could probably support; but for now
                        //   it's too complicated, so bail out
                        throw ctxt.mappingException("Can not create polymorphic instances with unwrapped values");
                    }
                    return .processUnwrapped(jpctxtbeantokens);
                }
                continue;
            }
            // Object Id property?
            if (buffer.readIdProperty(propName)) {
                continue;
            }
            // regular property? needs buffering
            SettableBeanProperty prop = .find(propName);
            if (prop != null) {
                buffer.bufferProperty(propprop.deserialize(jpctxt));
                continue;
            }
            /* As per [JACKSON-313], things marked as ignorable should not be
             * passed to any setter
             */
            if ( != null && .contains(propName)) {
                jp.skipChildren();
                continue;
            }
            tokens.writeFieldName(propName);
            tokens.copyCurrentStructure(jp);
            // "any property"?
            if ( != null) {
                buffer.bufferAnyProperty(propName.deserialize(jpctxt));
            }
        }
        // We hit END_OBJECT, so:
        Object bean;
        // !!! 15-Feb-2012, tatu: Need to modify creator to use Builder!
        try {
            bean = creator.build(ctxtbuffer);
        } catch (Exception e) {
            wrapInstantiationProblem(ectxt);
            return null// never gets here
        }
        return .processUnwrapped(jpctxtbeantokens);
    }
    /*
    /**********************************************************
    /* Handling for cases where we have property/-ies with
    /* external type id
    /**********************************************************
     */
    
        throws IOExceptionJsonProcessingException
    {
        if ( != null) {
            return deserializeUsingPropertyBasedWithExternalTypeId(jpctxt);
        }
        return deserializeWithExternalTypeId(jpctxt.createUsingDefault(ctxt));
    }
    		DeserializationContext ctxtObject bean)
        throws IOExceptionJsonProcessingException
    {
        final Class<?> activeView =  ? ctxt.getActiveView() : null;
        final ExternalTypeHandler ext = .start();
        for (; jp.getCurrentToken() != .jp.nextToken()) {
            String propName = jp.getCurrentName();
            jp.nextToken();
            SettableBeanProperty prop = .find(propName);
            if (prop != null) { // normal case
                if (activeView != null && !prop.visibleInView(activeView)) {
                    jp.skipChildren();
                    continue;
                }
                try {
                    bean = prop.deserializeSetAndReturn(jpctxtbean);
                } catch (Exception e) {
                    wrapAndThrow(ebeanpropNamectxt);
                }
                continue;
            }
            // ignorable things should be ignored
            if ( != null && .contains(propName)) {
                jp.skipChildren();
                continue;
            }
            // but others are likely to be part of external type id thingy...
            if (ext.handlePropertyValue(jpctxtpropNamebean)) {
                continue;
            }
            // if not, the usual fallback handling:
            if ( != null) {
                try {
                    .deserializeAndSet(jpctxtbeanpropName);
                } catch (Exception e) {
                    wrapAndThrow(ebeanpropNamectxt);
                }
                continue;
            } else {
                // Unknown: let's call handler method
                handleUnknownProperty(jpctxtbeanpropName);         
            }
        }
        // and when we get this far, let's try finalizing the deal:
        return ext.complete(jpctxtbean);
    }        
        throws IOExceptionJsonProcessingException
    {
        // !!! 04-Mar-2012, TODO: Need to fix -- will not work as is...
        throw new IllegalStateException("Deserialization with Builder, External type id, @JsonCreator not yet implemented");
    }
New to GrepCode? Check out our FAQ X