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/ser/impl/PropertySerializerMap.java

    package com.fasterxml.jackson.databind.ser.impl;
    
    import java.util.Arrays;
    
    import com.fasterxml.jackson.databind.BeanProperty;
    import com.fasterxml.jackson.databind.JavaType;
    import com.fasterxml.jackson.databind.JsonMappingException;
    import com.fasterxml.jackson.databind.JsonSerializer;
    import com.fasterxml.jackson.databind.SerializerProvider;
    
    /**
     * Helper container used for resolving serializers for dynamic (possibly but not
     * necessarily polymorphic) properties: properties whose type is not forced
     * to use dynamic (declared) type and that are not final.
     * If so, serializer to use can only be established once actual value type is known.
     * Since this happens a lot unless static typing is forced (or types are final)
     * this implementation is optimized for efficiency.
     * Instances are immutable; new instances are created with factory methods: this
     * is important to ensure correct multi-threaded access.
     */
    public abstract class PropertySerializerMap
    {
        /**
         * Configuration setting that determines what happens when maximum
         * size (currently 8) is reached: if true, will "start from beginning";
         * if false, will simply stop adding new entries.
         *
         * @since 2.5
         */
        protected final boolean _resetWhenFull;
    
        /**
         * @since 2.5
         */
        protected PropertySerializerMap(boolean resetWhenFull) {
            _resetWhenFull = resetWhenFull;
        }
    
        protected PropertySerializerMap(PropertySerializerMap base) {
            _resetWhenFull = base._resetWhenFull;
        }
    
        /**
         * Main lookup method. Takes a "raw" type since usage is always from
         * place where parameterization is fixed such that there cannot be
         * type-parametric variations.
         */
        public abstract JsonSerializer<Object> serializerFor(Class<?> type);
    
        /**
         * Method called if initial lookup fails, when looking for a primary
         * serializer (one that is directly attached to a property).
         * Will both find serializer
         * and construct new map instance if warranted, and return both.
         * 
         * @since 2.3
         * 
         * @throws JsonMappingException 
         */
        public final SerializerAndMapResult findAndAddPrimarySerializer(Class<?> type,
                SerializerProvider provider, BeanProperty property)
            throws JsonMappingException
        {
            JsonSerializer<Object> serializer = provider.findPrimaryPropertySerializer(type, property);
            return new SerializerAndMapResult(serializer, newWith(type, serializer));
        }
    
        public final SerializerAndMapResult findAndAddPrimarySerializer(JavaType type,
                SerializerProvider provider, BeanProperty property)
            throws JsonMappingException
        {
            JsonSerializer<Object> serializer = provider.findPrimaryPropertySerializer(type, property);
            return new SerializerAndMapResult(serializer, newWith(type.getRawClass(), serializer));
        }
    
        /**
         * Method called if initial lookup fails, when looking for a non-primary
         * serializer (one that is not directly attached to a property).
         * Will both find serializer
         * and construct new map instance if warranted, and return both.
         * 
         * @since 2.3
         * 
         * @throws JsonMappingException 
         */
        public final SerializerAndMapResult findAndAddSecondarySerializer(Class<?> type,
                SerializerProvider provider, BeanProperty property)
            throws JsonMappingException
        {
            JsonSerializer<Object> serializer = provider.findContentValueSerializer(type, property);
            return new SerializerAndMapResult(serializer, newWith(type, serializer));
        }
    
        public final SerializerAndMapResult findAndAddSecondarySerializer(JavaType type,
                SerializerProvider provider, BeanProperty property)
            throws JsonMappingException
        {
            JsonSerializer<Object> serializer = provider.findContentValueSerializer(type, property);
            return new SerializerAndMapResult(serializer, newWith(type.getRawClass(), serializer));
        }
    
        /**
         * Method called if initial lookup fails, when looking for a root value
         * serializer: one that is not directly attached to a property, but needs to
         * have {@link com.fasterxml.jackson.databind.jsontype.TypeSerializer} wrapped
         * around it. Will both find the serializer
         * and construct new map instance if warranted, and return both.
         * 
         * @since 2.5
         * 
         * @throws JsonMappingException 
         */
        public final SerializerAndMapResult findAndAddRootValueSerializer(Class<?> type,
                SerializerProvider provider)
            throws JsonMappingException
        {
            JsonSerializer<Object> serializer = provider.findTypedValueSerializer(type, false, null);
            return new SerializerAndMapResult(serializer, newWith(type, serializer));
        }
    
        /**
         * @since 2.5
         */
        public final SerializerAndMapResult findAndAddRootValueSerializer(JavaType type,
                SerializerProvider provider)
            throws JsonMappingException
        {
            JsonSerializer<Object> serializer = provider.findTypedValueSerializer(type, false, null);
            return new SerializerAndMapResult(serializer, newWith(type.getRawClass(), serializer));
        }
    
        /**
         * Method called if initial lookup fails, when looking for a key
         * serializer (possible attached indirectly to a property)
         * Will both find serializer
         * and construct new map instance if warranted, and return both.
         * 
         * @since 2.7
         */
        public final SerializerAndMapResult findAndAddKeySerializer(Class<?> type,
                SerializerProvider provider, BeanProperty property)
            throws JsonMappingException
        {
            JsonSerializer<Object> serializer = provider.findKeySerializer(type, property);
            return new SerializerAndMapResult(serializer, newWith(type, serializer));
        }
        
        /**
         * Method that can be used to 'register' a serializer that caller has resolved
         * without help of this map.
         * 
         * @since 2.5
         */
        public final SerializerAndMapResult addSerializer(Class<?> type, JsonSerializer<Object> serializer) {
            return new SerializerAndMapResult(serializer, newWith(type, serializer));
        }
    
        /**
         * @since 2.5
         */
        public final SerializerAndMapResult addSerializer(JavaType type, JsonSerializer<Object> serializer) {
            return new SerializerAndMapResult(serializer, newWith(type.getRawClass(), serializer));
        }
    
        public abstract PropertySerializerMap newWith(Class<?> type, JsonSerializer<Object> serializer);
    
        /**
         * @since 2.5
         */
        public static PropertySerializerMap emptyForProperties() {
            return Empty.FOR_PROPERTIES;
        }
    
        /**
         * @since 2.5
         */
        public static PropertySerializerMap emptyForRootValues() {
            return Empty.FOR_ROOT_VALUES;
        }
    
        /*
        /**********************************************************
        /* Helper classes
        /**********************************************************
         */
    
        /**
         * Value class used for returning tuple that has both serializer
         * that was retrieved and new map instance
         */
        public final static class SerializerAndMapResult
        {
            public final JsonSerializer<Object> serializer;
            public final PropertySerializerMap map;
            
            public SerializerAndMapResult(JsonSerializer<Object> serializer,
                    PropertySerializerMap map)
            {
                this.serializer = serializer;
                this.map = map;
            }
        }
    
        /**
         * Trivial container for bundling type + serializer entries.
         */
        private final static class TypeAndSerializer
        {
            public final Class<?> type;
            public final JsonSerializer<Object> serializer;
    
            public TypeAndSerializer(Class<?> type, JsonSerializer<Object> serializer) {
                this.type = type;
                this.serializer = serializer;
            }
        }
    
        /*
        /**********************************************************
        /* Implementations
        /**********************************************************
         */
    
        /**
         * Bogus instance that contains no serializers; used as the default
         * map with new serializers.
         */
        private final static class Empty extends PropertySerializerMap
        {
            // No root serializers; do not reset when full
            public final static Empty FOR_PROPERTIES = new Empty(false);
    
            // Yes, root serializers; do reset when full
            public final static Empty FOR_ROOT_VALUES = new Empty(true);
    
            protected Empty(boolean resetWhenFull) {
                super(resetWhenFull);
            }
            
            @Override
            public JsonSerializer<Object> serializerFor(Class<?> type) {
                return null; // empty, nothing to find
            }        
    
            @Override
            public PropertySerializerMap newWith(Class<?> type, JsonSerializer<Object> serializer) {
                return new Single(this, type, serializer);
            }
        }
    
        /**
         * Map that contains a single serializer; although seemingly silly
         * this is probably the most commonly used variant because many
         * theoretically dynamic or polymorphic types just have single
         * actual type.
         */
        private final static class Single extends PropertySerializerMap
        {
            private final Class<?> _type;
            private final JsonSerializer<Object> _serializer;
    
            public Single(PropertySerializerMap base, Class<?> type, JsonSerializer<Object> serializer) {
                super(base);
                _type = type;
                _serializer = serializer;
            }
    
            @Override
            public JsonSerializer<Object> serializerFor(Class<?> type)
            {
                if (type == _type) {
                    return _serializer;
                }
                return null;
            }
    
            @Override
            public PropertySerializerMap newWith(Class<?> type, JsonSerializer<Object> serializer) {
                return new Double(this, _type, _serializer, type, serializer);
            }
        }
    
        private final static class Double extends PropertySerializerMap
        {
            private final Class<?> _type1, _type2;
            private final JsonSerializer<Object> _serializer1, _serializer2;
    
            public Double(PropertySerializerMap base,
                    Class<?> type1, JsonSerializer<Object> serializer1,
                    Class<?> type2, JsonSerializer<Object> serializer2)
            {
                super(base);
                _type1 = type1;
                _serializer1 = serializer1;
                _type2 = type2;
                _serializer2 = serializer2;
            }
    
            @Override
            public JsonSerializer<Object> serializerFor(Class<?> type)
            {
                if (type == _type1) {
                    return _serializer1;
                }
                if (type == _type2) {
                    return _serializer2;
                }
                return null;
            }        
    
            @Override
            public PropertySerializerMap newWith(Class<?> type, JsonSerializer<Object> serializer) {
                // Ok: let's just create generic one
                TypeAndSerializer[] ts = new TypeAndSerializer[3];
                ts[0] = new TypeAndSerializer(_type1, _serializer1);
                ts[1] = new TypeAndSerializer(_type2, _serializer2);
                ts[2] = new TypeAndSerializer(type, serializer);
                return new Multi(this, ts);
            }
        }
        
        private final static class Multi extends PropertySerializerMap
        {
            /**
             * Let's limit number of serializers we actually cache; linear
             * lookup won't scale too well beyond smallish number, and if
             * we really want to support larger collections should use
             * a hash map. But it seems unlikely this is a common use
             * case so for now let's just stop building after hard-coded
             * limit. 8 sounds like a reasonable stab for now.
             */
            private final static int MAX_ENTRIES = 8;
            
            private final TypeAndSerializer[] _entries;
    
            public Multi(PropertySerializerMap base, TypeAndSerializer[] entries) {
                super(base);
                _entries = entries;
            }
    
            @Override
            public JsonSerializer<Object> serializerFor(Class<?> type)
            {
                // Always have first 3 populated so
                TypeAndSerializer entry;
                entry = _entries[0];
                if (entry.type == type) return entry.serializer;
                entry = _entries[1];
                if (entry.type == type) return entry.serializer;
                entry = _entries[2];
                if (entry.type == type) return entry.serializer;
    
                switch (_entries.length) {
                case 8:
                    entry = _entries[7];
                    if (entry.type == type) return entry.serializer;
                case 7:
                    entry = _entries[6];
                    if (entry.type == type) return entry.serializer;
                case 6:
                    entry = _entries[5];
                    if (entry.type == type) return entry.serializer;
                case 5:
                    entry = _entries[4];
                    if (entry.type == type) return entry.serializer;
                case 4:
                    entry = _entries[3];
                    if (entry.type == type) return entry.serializer;
                default:
                }
                return null;
            }
    
            @Override
            public PropertySerializerMap newWith(Class<?> type, JsonSerializer<Object> serializer)
            {
                int len = _entries.length;
                // Will only grow up to N entries. We could consider couple of alternatives after
                // this if we wanted to... but for now, two main choices make most sense
                if (len == MAX_ENTRIES) {
                    if (_resetWhenFull) {
                        return new Single(this, type, serializer);
                    }
                    return this;
                }
                TypeAndSerializer[] entries = Arrays.copyOf(_entries, len+1);
                entries[len] = new TypeAndSerializer(type, serializer);
                return new Multi(this, entries);
            }
        }
    }
    

    com/fasterxml/jackson/databind/ser/impl/PropertySerializerMap.java

     

    ⇒ Jackson Annotations Source Code

    ⇐ Download and Install Jackson Binary Package

    ⇑ Downloading and Reviewing jackson-*.jar

    ⇑⇑ Jackson - Java JSON library

    2022-03-29, 32117👍, 0💬