Jackson Data Binding Source Code

Jackson is "the Java JSON library" or "the best JSON parser for Java". Or simply as "JSON for Java".

  • Jackson Data Binding module allows you to converts JSON to and from POJO (Plain Old Java Object) using property accessor or using annotations.
  • Jackson Databind Source Code files are provided in the source packge (jackson-databind-2.12.4-sources.jar). You can download it at Jackson Maven Website.

    You can also browse Jackson Databind Source Code below:

    ✍: FYIcenter.com

    com/fasterxml/jackson/databind/deser/impl/CreatorCollector.java

    package com.fasterxml.jackson.databind.deser.impl;
    
    import java.lang.reflect.Member;
    import java.util.*;
    
    import com.fasterxml.jackson.databind.*;
    import com.fasterxml.jackson.databind.cfg.MapperConfig;
    import com.fasterxml.jackson.databind.deser.SettableBeanProperty;
    import com.fasterxml.jackson.databind.deser.ValueInstantiator;
    import com.fasterxml.jackson.databind.deser.std.StdValueInstantiator;
    import com.fasterxml.jackson.databind.introspect.*;
    import com.fasterxml.jackson.databind.util.ClassUtil;
    
    /**
     * Container class for storing information on creators (based on annotations,
     * visibility), to be able to build actual {@code ValueInstantiator} later on.
     */
    public class CreatorCollector
    {
        protected final static int C_DEFAULT = 0;
        protected final static int C_STRING = 1;
        protected final static int C_INT = 2;
        protected final static int C_LONG = 3;
        protected final static int C_BIG_INTEGER = 4;
        protected final static int C_DOUBLE = 5;
        protected final static int C_BIG_DECIMAL = 6;
        protected final static int C_BOOLEAN = 7;
        protected final static int C_DELEGATE = 8;
        protected final static int C_PROPS = 9;
        protected final static int C_ARRAY_DELEGATE = 10;
    
        protected final static String[] TYPE_DESCS = new String[] { "default",
                "from-String", "from-int", "from-long", "from-big-integer", "from-double",
                "from-big-decimal", "from-boolean", "delegate", "property-based", "array-delegate"
        };
    
        /**
         * Type of bean being created
         */
        protected final BeanDescription _beanDesc;
    
        protected final boolean _canFixAccess;
    
        /**
         * @since 2.7
         */
        protected final boolean _forceAccess;
    
        /**
         * Set of creators we have collected so far
         * 
         * @since 2.5
         */
        protected final AnnotatedWithParams[] _creators = new AnnotatedWithParams[11];
    
        /**
         * Bitmask of creators that were explicitly marked as creators; false for
         * auto-detected (ones included base on naming and/or visibility, not
         * annotation)
         *
         * @since 2.5
         */
        protected int _explicitCreators = 0;
    
        protected boolean _hasNonDefaultCreator = false;
    
        // when there are injectable values along with delegate:
        protected SettableBeanProperty[] _delegateArgs;
    
        protected SettableBeanProperty[] _arrayDelegateArgs;
    
        protected SettableBeanProperty[] _propertyBasedArgs;
    
        /*
        /**********************************************************
        /* Life-cycle
        /**********************************************************
         */
    
        public CreatorCollector(BeanDescription beanDesc, MapperConfig<?> config) {
            _beanDesc = beanDesc;
            _canFixAccess = config.canOverrideAccessModifiers();
            _forceAccess = config
                    .isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS);
        }
    
        public ValueInstantiator constructValueInstantiator(DeserializationContext ctxt)
            throws JsonMappingException
        {
            final DeserializationConfig config = ctxt.getConfig();
            final JavaType delegateType = _computeDelegateType(ctxt,
                    _creators[C_DELEGATE], _delegateArgs);
            final JavaType arrayDelegateType = _computeDelegateType(ctxt,
                    _creators[C_ARRAY_DELEGATE], _arrayDelegateArgs);
            final JavaType type = _beanDesc.getType();
    
            StdValueInstantiator inst = new StdValueInstantiator(config, type);
            inst.configureFromObjectSettings(_creators[C_DEFAULT], _creators[C_DELEGATE],
                    delegateType, _delegateArgs, _creators[C_PROPS],
                    _propertyBasedArgs);
            inst.configureFromArraySettings(_creators[C_ARRAY_DELEGATE],
                    arrayDelegateType, _arrayDelegateArgs);
            inst.configureFromStringCreator(_creators[C_STRING]);
            inst.configureFromIntCreator(_creators[C_INT]);
            inst.configureFromLongCreator(_creators[C_LONG]);
            inst.configureFromBigIntegerCreator(_creators[C_BIG_INTEGER]);
            inst.configureFromDoubleCreator(_creators[C_DOUBLE]);
            inst.configureFromBigDecimalCreator(_creators[C_BIG_DECIMAL]);
            inst.configureFromBooleanCreator(_creators[C_BOOLEAN]);
            return inst;
        }
    
        /*
        /**********************************************************
        /* Setters
        /**********************************************************
         */
    
        /**
         * Method called to indicate the default creator: no-arguments constructor
         * or factory method that is called to instantiate a value before populating
         * it with data. Default creator is only used if no other creators are
         * indicated.
         * 
         * @param creator
         *            Creator method; no-arguments constructor or static factory
         *            method.
         */
        public void setDefaultCreator(AnnotatedWithParams creator) {
            _creators[C_DEFAULT] = _fixAccess(creator);
        }
    
        public void addStringCreator(AnnotatedWithParams creator, boolean explicit) {
            verifyNonDup(creator, C_STRING, explicit);
        }
    
        public void addIntCreator(AnnotatedWithParams creator, boolean explicit) {
            verifyNonDup(creator, C_INT, explicit);
        }
    
        public void addLongCreator(AnnotatedWithParams creator, boolean explicit) {
            verifyNonDup(creator, C_LONG, explicit);
        }
    
        public void addBigIntegerCreator(AnnotatedWithParams creator, boolean explicit) {
            verifyNonDup(creator, C_BIG_INTEGER, explicit);
        }
    
        public void addDoubleCreator(AnnotatedWithParams creator, boolean explicit) {
            verifyNonDup(creator, C_DOUBLE, explicit);
        }
    
        public void addBigDecimalCreator(AnnotatedWithParams creator, boolean explicit) {
            verifyNonDup(creator, C_BIG_DECIMAL, explicit);
        }
    
        public void addBooleanCreator(AnnotatedWithParams creator, boolean explicit) {
            verifyNonDup(creator, C_BOOLEAN, explicit);
        }
    
        public void addDelegatingCreator(AnnotatedWithParams creator,
                boolean explicit, SettableBeanProperty[] injectables,
                int delegateeIndex)
        {
            if (creator.getParameterType(delegateeIndex).isCollectionLikeType()) {
                if (verifyNonDup(creator, C_ARRAY_DELEGATE, explicit)) {
                    _arrayDelegateArgs = injectables;
                }
            } else {
                if (verifyNonDup(creator, C_DELEGATE, explicit)) {
                    _delegateArgs = injectables;
                }
            }
        }
    
        public void addPropertyCreator(AnnotatedWithParams creator,
                boolean explicit, SettableBeanProperty[] properties)
        {
            if (verifyNonDup(creator, C_PROPS, explicit)) {
                // Better ensure we have no duplicate names either...
                if (properties.length > 1) {
                    HashMap<String, Integer> names = new HashMap<String, Integer>();
                    for (int i = 0, len = properties.length; i < len; ++i) {
                        String name = properties[i].getName();
                        // Need to consider Injectables, which may not have
                        // a name at all, and need to be skipped
                        if (name.isEmpty() && (properties[i].getInjectableValueId() != null)) {
                            continue;
                        }
                        Integer old = names.put(name, Integer.valueOf(i));
                        if (old != null) {
                            throw new IllegalArgumentException(String.format(
                                    "Duplicate creator property \"%s\" (index %s vs %d) for type %s ",
                                    name, old, i, ClassUtil.nameOf(_beanDesc.getBeanClass())));
                        }
                    }
                }
                _propertyBasedArgs = properties;
            }
        }
    
        /*
        /**********************************************************
        /* Accessors
        /**********************************************************
         */
    
        /**
         * @since 2.1
         */
        public boolean hasDefaultCreator() {
            return _creators[C_DEFAULT] != null;
        }
    
        /**
         * @since 2.6
         */
        public boolean hasDelegatingCreator() {
            return _creators[C_DELEGATE] != null;
        }
    
        /**
         * @since 2.6
         */
        public boolean hasPropertyBasedCreator() {
            return _creators[C_PROPS] != null;
        }
    
        /*
        /**********************************************************
        /* Helper methods
        /**********************************************************
         */
    
        private JavaType _computeDelegateType(DeserializationContext ctxt,
                AnnotatedWithParams creator, SettableBeanProperty[] delegateArgs)
            throws JsonMappingException
        {
            if (!_hasNonDefaultCreator || (creator == null)) {
                return null;
            }
            // need to find type...
            int ix = 0;
            if (delegateArgs != null) {
                for (int i = 0, len = delegateArgs.length; i < len; ++i) {
                    if (delegateArgs[i] == null) { // marker for delegate itself
                        ix = i;
                        break;
                    }
                }
            }
            final DeserializationConfig config = ctxt.getConfig();
    
            // 03-May-2018, tatu: need to check possible annotation-based
            //   custom deserializer [databind#2012],
            //   type refinement(s) [databind#2016]. 
            JavaType baseType = creator.getParameterType(ix);
            AnnotationIntrospector intr = config.getAnnotationIntrospector();
            if (intr != null) {
                AnnotatedParameter delegate = creator.getParameter(ix);
                
                // First: custom deserializer(s):
                Object deserDef = intr.findDeserializer(delegate);
                if (deserDef != null) {
                    JsonDeserializer<Object> deser = ctxt.deserializerInstance(delegate, deserDef);
                    baseType = baseType.withValueHandler(deser);
                } else {
                    // Second: type refinement(s), if no explicit deserializer was located
                    baseType = intr.refineDeserializationType(config,
                            delegate, baseType);
                }
            }
            return baseType;
        }
    
        private <T extends AnnotatedMember> T _fixAccess(T member) {
            if (member != null && _canFixAccess) {
                ClassUtil.checkAndFixAccess((Member) member.getAnnotated(),
                        _forceAccess);
            }
            return member;
        }
    
        /**
         * @return True if specified Creator is to be used
         */
        protected boolean verifyNonDup(AnnotatedWithParams newOne, int typeIndex, boolean explicit)
        {
            final int mask = (1 << typeIndex);
            _hasNonDefaultCreator = true;
            AnnotatedWithParams oldOne = _creators[typeIndex];
            // already had an explicitly marked one?
            if (oldOne != null) {
                boolean verify;
                if ((_explicitCreators & mask) != 0) { // already had explicitly annotated, leave as-is
                    // but skip, if new one not annotated
                    if (!explicit) {
                        return false;
                    }
                    // both explicit: verify
                    verify = true;
                } else {
                    // otherwise only verify if neither explicitly annotated.
                    verify = !explicit;
                }
    
                // one more thing: ok to override in sub-class
                // 23-Feb-2021, tatu: Second check is for case of static factory vs constructor,
                //    which is handled by caller, presumably.
                //    Removing it would fail one test (in case interested).
                if (verify && (oldOne.getClass() == newOne.getClass())) {
                    // [databind#667]: avoid one particular class of bogus problems
                    final Class<?> oldType = oldOne.getRawParameterType(0);
                    final Class<?> newType = newOne.getRawParameterType(0);
    
                    if (oldType == newType) {
                        // 13-Jul-2016, tatu: One more thing to check; since Enum classes
                        //   always have implicitly created `valueOf()`, let's resolve in
                        //   favor of other implicit creator (`fromString()`)
                        if (_isEnumValueOf(newOne)) {
                            return false; // ignore
                        }
                        if (_isEnumValueOf(oldOne)) {
                            ;
                        } else {
                            _reportDuplicateCreator(typeIndex, explicit, oldOne, newOne);
                        }
                    }
                    // otherwise, which one to choose?
                    else if (newType.isAssignableFrom(oldType)) {
                        // new type less specific use old
                        return false;
                    } else if (oldType.isAssignableFrom(newType)) {
                        // new type more specific, use it
                        ;
                        // 23-Feb-2021, tatu: due to [databind#3062], backwards-compatibility,
                        //   let's allow "primitive/Wrapper" case and tie-break in favor
                        //   of PRIMITIVE argument (null would never map to scalar creators,
                        //   and fundamentally all we need is a tie-breaker: up to caller to
                        //   annotate if wants the wrapper one)
                    } else if (oldType.isPrimitive() != newType.isPrimitive()) {
                        // Prefer primitive one
                        if (oldType.isPrimitive()) {
                            return false;
                        }
                    } else {
                        // 02-May-2020, tatu: Should this only result in exception if both
                        //   explicit? Doing so could lead to arbitrary choice between
                        //   multiple implicit creators tho?
                        _reportDuplicateCreator(typeIndex, explicit, oldOne, newOne);
                    }
                }
            }
            if (explicit) {
                _explicitCreators |= mask;
            }
            _creators[typeIndex] = _fixAccess(newOne);
            return true;
        }
    
        // @since 2.12
        protected void _reportDuplicateCreator(int typeIndex, boolean explicit,
                AnnotatedWithParams oldOne, AnnotatedWithParams newOne) {
            throw new IllegalArgumentException(String.format(
                    "Conflicting %s creators: already had %s creator %s, encountered another: %s",
                    TYPE_DESCS[typeIndex],
                    explicit ? "explicitly marked"
                            : "implicitly discovered",
                    oldOne, newOne));
        }
        
        /**
         * Helper method for recognizing `Enum.valueOf()` factory method
         *
         * @since 2.8.1
         */
        protected boolean _isEnumValueOf(AnnotatedWithParams creator) {
            return ClassUtil.isEnumType(creator.getDeclaringClass())
                    && "valueOf".equals(creator.getName());
        }
    }
    

    com/fasterxml/jackson/databind/deser/impl/CreatorCollector.java

     

    ⇒ Jackson Annotations Source Code

    ⇐ Download and Install Jackson Binary Package

    ⇑ Downloading and Reviewing jackson-*.jar

    ⇑⇑ Jackson - Java JSON library

    2022-03-29, 32024👍, 0💬