Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  package com.fasterxml.jackson.databind.deser.impl;
  
  import java.util.*;
  
  
Helper class that is used to flatten JSON structure when using "external type id" (see com.fasterxml.jackson.annotation.JsonTypeInfo.As.EXTERNAL_PROPERTY). This is needed to store temporary state and buffer tokens, as the structure is rearranged a bit so that actual type deserializer can resolve type and finalize deserialization.
 
 public class ExternalTypeHandler
 {
     private final ExtTypedProperty[] _properties;
     private final HashMap<StringInteger_nameToPropertyIndex;
 
     private final String[] _typeIds;
     private final TokenBuffer[] _tokens;
     
     protected ExternalTypeHandler(ExtTypedProperty[] properties,
             HashMap<StringIntegernameToPropertyIndex,
             String[] typeIdsTokenBuffer[] tokens)
     {
          = properties;        
          = nameToPropertyIndex;
          = typeIds;
          = tokens;
     }
 
     {
          = h._properties;
          = h._nameToPropertyIndex;
         int len = .;
          = new String[len];
          = new TokenBuffer[len];
     }
     
     public ExternalTypeHandler start() {
         return new ExternalTypeHandler(this);
     }

    
Method called to see if given property/value pair is an external type id; and if so handle it. This is only to be called in case containing POJO has similarly named property as the external type id; otherwise handlePropertyValue(com.fasterxml.jackson.core.JsonParser,com.fasterxml.jackson.databind.DeserializationContext,java.lang.String,java.lang.Object) should be called instead.
 
     public boolean handleTypePropertyValue(JsonParser jpDeserializationContext ctxt,
             String propNameObject bean)
         throws IOExceptionJsonProcessingException
     {
         Integer I = .get(propName);
         if (I == null) {
             return false;
         }
         int index = I.intValue();
         ExtTypedProperty prop = [index];
         if (!prop.hasTypePropertyName(propName)) {
             return false;
         }
         [index] = jp.getText();
         // note: can NOT skip child values (should always be String anyway)
         boolean canDeserialize = (bean != null) && ([index] != null);
         // Minor optimization: deserialize properties as soon as we have all we need:
         if (canDeserialize) {
             _deserializeAndSet(jpctxtbeanindex);
             // clear stored data, to avoid deserializing+setting twice:
             [index] = null;
             [index] = null;
         }
         return true;
     }
    
    
Method called to ask handler to handle value of given property, at point where parser points to the first token of the value. Handling can mean either resolving type id it contains (if it matches type property name), or by buffering the value for further use.

Returns:
True, if the given property was properly handled
 
     public boolean handlePropertyValue(JsonParser jpDeserializationContext ctxt,
             String propNameObject bean)
         throws IOExceptionJsonProcessingException
     {
         Integer I = .get(propName);
         if (I == null) {
             return false;
         }
         int index = I.intValue();
         ExtTypedProperty prop = [index];
        boolean canDeserialize;
        if (prop.hasTypePropertyName(propName)) {
            [index] = jp.getText();
            jp.skipChildren();
            canDeserialize = (bean != null) && ([index] != null);
        } else {
            TokenBuffer tokens = new TokenBuffer(jp.getCodec());
            tokens.copyCurrentStructure(jp);
            [index] = tokens;
            canDeserialize = (bean != null) && ([index] != null);
        }
        /* Minor optimization: let's deserialize properties as soon as
         * we have all pertinent information:
         */
        if (canDeserialize) {
            _deserializeAndSet(jpctxtbeanindex);
            // clear stored data, to avoid deserializing+setting twice:
            [index] = null;
            [index] = null;
        }
        return true;
    }
    
    public Object complete(JsonParser jpDeserializationContext ctxtObject bean)
        throws IOExceptionJsonProcessingException
    {
        for (int i = 0, len = .i < len; ++i) {
            if ([i] == null) {
                // let's allow missing both type and property (may already have been set, too)
                if ([i] == null) {
                    continue;
                }
                // but not just one
                throw ctxt.mappingException("Missing external type id property '"+[i].getTypePropertyName());
            } else if ([i] == null) {
                SettableBeanProperty prop = [i].getProperty();
                throw ctxt.mappingException("Missing property '"+prop.getName()+"' for external type id '"+[i].getTypePropertyName());
            }
            _deserializeAndSet(jpctxtbeani);
        }
        return bean;
    }

    
Variant called when creation of the POJO involves buffering of creator properties as well as property-based creator.
    public Object complete(JsonParser jpDeserializationContext ctxt,
            PropertyValueBuffer bufferPropertyBasedCreator creator)
        throws IOExceptionJsonProcessingException
    {
        // first things first: deserialize all data buffered:
        final int len = .;
        Object[] values = new Object[len];
        for (int i = 0; i < len; ++i) {
            if ([i] == null) {
                // let's allow missing both type and property (may already have been set, too)
                if ([i] == null) {
                    continue;
                }
                // but not just one
                throw ctxt.mappingException("Missing external type id property '"+[i].getTypePropertyName());
            } else if ([i] == null) {
                SettableBeanProperty prop = [i].getProperty();
                throw ctxt.mappingException("Missing property '"+prop.getName()+"' for external type id '"+[i].getTypePropertyName());
            }
            values[i] = _deserialize(jpctxti);
        }
        // second: fill in creator properties:
        for (int i = 0; i < len; ++i) {
            SettableBeanProperty prop = [i].getProperty();
            if (creator.findCreatorProperty(prop.getName()) != null) {
                buffer.assignParameter(prop.getCreatorIndex(), values[i]);
            }
        }
        Object bean = creator.build(ctxtbuffer);
        // third: assign non-creator properties
        for (int i = 0; i < len; ++i) {
            SettableBeanProperty prop = [i].getProperty();
            if (creator.findCreatorProperty(prop.getName()) == null) {
                prop.set(beanvalues[i]);
            }
        }
        return bean;
    }
    protected final Object _deserialize(JsonParser jpDeserializationContext ctxt,
            int index)
        throws IOExceptionJsonProcessingException
    {
        TokenBuffer merged = new TokenBuffer(jp.getCodec());
        merged.writeStartArray();
        merged.writeString([index]);
        JsonParser p2 = [index].asParser(jp);
        p2.nextToken();
        merged.copyCurrentStructure(p2);
        merged.writeEndArray();
        // needs to point to START_OBJECT (or whatever first token is)
        p2 = merged.asParser(jp);
        p2.nextToken();
        return [index].getProperty().deserialize(p2ctxt);
    }
    
    protected final void _deserializeAndSet(JsonParser jpDeserializationContext ctxtObject beanint index)
        throws IOExceptionJsonProcessingException
    {
        /* Ok: time to mix type id, value; and we will actually use "wrapper-array"
         * style to ensure we can handle all kinds of JSON constructs.
         */
        TokenBuffer merged = new TokenBuffer(jp.getCodec());
        merged.writeStartArray();
        merged.writeString([index]);
        JsonParser p2 = [index].asParser(jp);
        p2.nextToken();
        merged.copyCurrentStructure(p2);
        merged.writeEndArray();
        // needs to point to START_OBJECT (or whatever first token is)
        p2 = merged.asParser(jp);
        p2.nextToken();
        [index].getProperty().deserializeAndSet(p2ctxtbean);
    }
    
    /*
    /**********************************************************
    /* Helper classes
    /**********************************************************
     */
    
    public static class Builder
    {
        private final ArrayList<ExtTypedProperty_properties = new ArrayList<ExtTypedProperty>();
        private final HashMap<StringInteger_nameToPropertyIndex = new HashMap<StringInteger>();
        
        public void addExternal(SettableBeanProperty propertyString extPropName)
        {
            Integer index = .size();
            .add(new ExtTypedProperty(propertyextPropName));
            .put(property.getName(), index);
            .put(extPropNameindex);
        }
        
        public ExternalTypeHandler build() {
            return new ExternalTypeHandler(.toArray(new ExtTypedProperty[.size()]),
                    nullnull);
        }
    }
    private final static class ExtTypedProperty
    {
        private final SettableBeanProperty _property;
        private final String _typePropertyName;
        
        public ExtTypedProperty(SettableBeanProperty propertyString typePropertyName)
        {
             = property;
             = typePropertyName;
        }
        public boolean hasTypePropertyName(String n) {
            return n.equals();
        }
        public String getTypePropertyName() { return ; }
        
        public SettableBeanProperty getProperty() {
            return ;
        }
    }
New to GrepCode? Check out our FAQ X