Jackson Annotations Source Code

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

Jackson Annotations Source Code files are provided in the source packge (jackson-annotations-2.12.4-sources.jar). You can download it at Jackson Maven Website.

You can also browse Jackson Annotations 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 Dataformat Extensions

⇐ Jackson Data Binding Source Code

⇑ Downloading and Reviewing jackson-*.jar

⇑⇑ Jackson - Java JSON library

2022-02-19, 36159👍, 0💬