CommonsLangSerializers.java

package top.infra.jackson2;

import com.fasterxml.jackson.databind.AnnotationIntrospector;
import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializationConfig;
import com.fasterxml.jackson.databind.introspect.AnnotatedClass;
import com.fasterxml.jackson.databind.jsontype.NamedType;
import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder;
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
import com.fasterxml.jackson.databind.ser.Serializers;

import org.apache.commons.lang3.tuple.Pair;

import java.util.Collection;

import top.infra.jackson2.ser.PairSerializer;

/**
 * {@link com.fasterxml.jackson.databind.ser.BasicSerializerFactory#buildMapEntrySerializer(SerializationConfig, JavaType, BeanDescription, boolean, JavaType, JavaType)}.
 * {@link com.fasterxml.jackson.databind.ser.BeanSerializerFactory}
 * com.fasterxml.jackson.datatype.guava.GuavaSerializers
 */
public class CommonsLangSerializers extends Serializers.Base {

    @Override
    public JsonSerializer<?> findSerializer(
        final SerializationConfig config, final JavaType type, final BeanDescription beanDesc) {
        // see: BasicSerializerFactory.buildContainerSerializer
        if (Pair.class.isAssignableFrom(type.getRawClass())) {
            // Let's see what we can learn about element/content/value type, type serializer for it:
            JavaType lType = type.containedTypeOrUnknown(0);
            JavaType rType = type.containedTypeOrUnknown(1);
            boolean staticTyping = false;
            final TypeSerializer kts = createTypeSerializer(config, lType);
            final TypeSerializer vts = createTypeSerializer(config, rType);
            return new PairSerializer(type, lType, rType, staticTyping, kts, vts, null);
        }
        return super.findSerializer(config, type, beanDesc);
    }

    /**
     * see: {@link com.fasterxml.jackson.databind.ser.BasicSerializerFactory#createTypeSerializer(SerializationConfig, JavaType)}.
     */
    public TypeSerializer createTypeSerializer(final SerializationConfig config, final JavaType baseType) {
        if (baseType == null) {
            return null;
        }
        final BeanDescription bean = config.introspectClassAnnotations(baseType.getRawClass());
        final AnnotatedClass ac = bean.getClassInfo();
        final AnnotationIntrospector ai = config.getAnnotationIntrospector();
        TypeResolverBuilder<?> b = ai.findTypeResolver(config, ac, baseType);
        /* Ok: if there is no explicit type info handler, we may want to
         * use a default. If so, config object knows what to use.
         */
        Collection<NamedType> subtypes = null;
        if (b == null) {
            b = config.getDefaultTyper(baseType);
        } else {
            subtypes = config.getSubtypeResolver().collectAndResolveSubtypesByClass(config, ac);
        }
        if (b == null) {
            return null;
        }
        // 10-Jun-2015, tatu: Since not created for Bean Property, no need for post-processing
        //    wrt EXTERNAL_PROPERTY
        return b.buildTypeSerializer(config, baseType, subtypes);
    }
}