com.fitbur.jackson.databind.module.SimpleSerializers Maven / Gradle / Ivy
package com.fitbur.jackson.databind.module;
import java.util.*;
import com.fitbur.jackson.databind.*;
import com.fitbur.jackson.databind.jsontype.TypeSerializer;
import com.fitbur.jackson.databind.ser.Serializers;
import com.fitbur.jackson.databind.type.ArrayType;
import com.fitbur.jackson.databind.type.ClassKey;
import com.fitbur.jackson.databind.type.CollectionLikeType;
import com.fitbur.jackson.databind.type.CollectionType;
import com.fitbur.jackson.databind.type.MapLikeType;
import com.fitbur.jackson.databind.type.MapType;
/**
* Simple implementation {@link Serializers} which allows registration of
* serializers based on raw (type erased class).
* It can work well for basic bean and scalar type serializers, but is not
* a good fit for handling generic types (like {@link Map}s and {@link Collection}s).
*
* Type registrations are assumed to be general; meaning that registration of serializer
* for a super type will also be used for handling subtypes, unless an exact match
* is found first. As an example, handler for {@link CharSequence} would also be used
* serializing {@link StringBuilder} instances, unless a direct mapping was found.
*/
public class SimpleSerializers
extends Serializers.Base
implements java.io.Serializable
{
private static final long serialVersionUID = 8531646511998456779L;
/**
* Class-based mappings that are used both for exact and
* sub-class matches.
*/
protected HashMap> _classMappings = null;
/**
* Interface-based matches.
*/
protected HashMap> _interfaceMappings = null;
/**
* Flag to help find "generic" enum serializer, if one has been registered.
*
* @since 2.3
*/
protected boolean _hasEnumSerializer = false;
/*
/**********************************************************
/* Life-cycle, construction and configuring
/**********************************************************
*/
public SimpleSerializers() { }
/**
* @since 2.1
*/
public SimpleSerializers(List> sers) {
addSerializers(sers);
}
/**
* Method for adding given serializer for type that {@link JsonSerializer#handledType}
* specifies (which MUST return a non-null class; and can NOT be {@link Object}, as a
* sanity check).
* For serializers that do not declare handled type, use the variant that takes
* two arguments.
*
* @param ser
*/
public void addSerializer(JsonSerializer> ser)
{
// Interface to match?
Class> cls = ser.handledType();
if (cls == null || cls == Object.class) {
throw new IllegalArgumentException("JsonSerializer of type "+ser.getClass().getName()
+" does not define valid handledType() -- must either register with method that takes type argument "
+" or make serializer extend 'com.fitbur.jackson.databind.ser.std.StdSerializer'");
}
_addSerializer(cls, ser);
}
public void addSerializer(Class extends T> type, JsonSerializer ser)
{
_addSerializer(type, ser);
}
/**
* @since 2.1
*/
public void addSerializers(List> sers) {
for (JsonSerializer> ser : sers) {
addSerializer(ser);
}
}
/*
/**********************************************************
/* Serializers implementation
/**********************************************************
*/
@Override
public JsonSerializer> findSerializer(SerializationConfig config,
JavaType type, BeanDescription beanDesc)
{
Class> cls = type.getRawClass();
ClassKey key = new ClassKey(cls);
JsonSerializer> ser = null;
// First: direct match?
if (cls.isInterface()) {
if (_interfaceMappings != null) {
ser = _interfaceMappings.get(key);
if (ser != null) {
return ser;
}
}
} else {
if (_classMappings != null) {
ser = _classMappings.get(key);
if (ser != null) {
return ser;
}
// [Issue#227]: Handle registration of plain `Enum` serializer
if (_hasEnumSerializer && type.isEnumType()) {
key.reset(Enum.class);
ser = _classMappings.get(key);
if (ser != null) {
return ser;
}
}
// If not direct match, maybe super-class match?
for (Class> curr = cls; (curr != null); curr = curr.getSuperclass()) {
key.reset(curr);
ser = _classMappings.get(key);
if (ser != null) {
return ser;
}
}
}
}
// No direct match? How about super-interfaces?
if (_interfaceMappings != null) {
ser = _findInterfaceMapping(cls, key);
if (ser != null) {
return ser;
}
// still no matches? Maybe interfaces of super classes
if (!cls.isInterface()) {
while ((cls = cls.getSuperclass()) != null) {
ser = _findInterfaceMapping(cls, key);
if (ser != null) {
return ser;
}
}
}
}
return null;
}
@Override
public JsonSerializer> findArraySerializer(SerializationConfig config,
ArrayType type, BeanDescription beanDesc,
TypeSerializer elementTypeSerializer, JsonSerializer