package com.fasterxml.jackson.databind.ser.std;
import java.io.IOException;
import java.util.Calendar;
import java.util.Date;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
import com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap;
import com.fasterxml.jackson.databind.util.ClassUtil;
import com.fasterxml.jackson.databind.util.EnumValues;
@SuppressWarnings("serial")
public abstract class StdKeySerializers
{
@SuppressWarnings("deprecation")
protected final static JsonSerializer<Object> DEFAULT_KEY_SERIALIZER = new StdKeySerializer();
protected final static JsonSerializer<Object> DEFAULT_STRING_SERIALIZER = new StringKeySerializer();
public static JsonSerializer<Object> getStdKeySerializer(SerializationConfig config,
Class<?> rawKeyType, boolean useDefault)
{
if ((rawKeyType == null) || (rawKeyType == Object.class)) {
return new Dynamic();
}
if (rawKeyType == String.class) {
return DEFAULT_STRING_SERIALIZER;
}
if (rawKeyType.isPrimitive()) {
rawKeyType = ClassUtil.wrapperType(rawKeyType);
}
if (rawKeyType == Integer.class) {
return new Default(Default.TYPE_INTEGER, rawKeyType);
}
if (rawKeyType == Long.class) {
return new Default(Default.TYPE_LONG, rawKeyType);
}
if (rawKeyType.isPrimitive() || Number.class.isAssignableFrom(rawKeyType)) {
return new Default(Default.TYPE_TO_STRING, rawKeyType);
}
if (rawKeyType == Class.class) {
return new Default(Default.TYPE_CLASS, rawKeyType);
}
if (Date.class.isAssignableFrom(rawKeyType)) {
return new Default(Default.TYPE_DATE, rawKeyType);
}
if (Calendar.class.isAssignableFrom(rawKeyType)) {
return new Default(Default.TYPE_CALENDAR, rawKeyType);
}
if (rawKeyType == java.util.UUID.class) {
return new Default(Default.TYPE_TO_STRING, rawKeyType);
}
if (rawKeyType == byte[].class) {
return new Default(Default.TYPE_BYTE_ARRAY, rawKeyType);
}
if (useDefault) {
return new Default(Default.TYPE_TO_STRING, rawKeyType);
}
return null;
}
@SuppressWarnings("unchecked")
public static JsonSerializer<Object> getFallbackKeySerializer(SerializationConfig config,
Class<?> rawKeyType)
{
if (rawKeyType != null) {
if (rawKeyType == Enum.class) {
return new Dynamic();
}
if (ClassUtil.isEnumType(rawKeyType)) {
return EnumKeySerializer.construct(rawKeyType,
EnumValues.constructFromName(config, (Class<Enum<?>>) rawKeyType));
}
}
return new Default(Default.TYPE_TO_STRING, rawKeyType);
}
@Deprecated
public static JsonSerializer<Object> getDefault() {
return DEFAULT_KEY_SERIALIZER;
}
public static class Default extends StdSerializer<Object> {
final static int TYPE_DATE = 1;
final static int TYPE_CALENDAR = 2;
final static int TYPE_CLASS = 3;
final static int TYPE_ENUM = 4;
final static int TYPE_INTEGER = 5;
final static int TYPE_LONG = 6;
final static int TYPE_BYTE_ARRAY = 7;
final static int TYPE_TO_STRING = 8;
protected final int _typeId;
public Default(int typeId, Class<?> type) {
super(type, false);
_typeId = typeId;
}
@Override
public void serialize(Object value, JsonGenerator g, SerializerProvider provider) throws IOException {
switch (_typeId) {
case TYPE_DATE:
provider.defaultSerializeDateKey((Date)value, g);
break;
case TYPE_CALENDAR:
provider.defaultSerializeDateKey(((Calendar) value).getTimeInMillis(), g);
break;
case TYPE_CLASS:
g.writeFieldName(((Class<?>)value).getName());
break;
case TYPE_ENUM:
{
String key;
if (provider.isEnabled(SerializationFeature.WRITE_ENUMS_USING_TO_STRING)) {
key = value.toString();
} else {
Enum<?> e = (Enum<?>) value;
if (provider.isEnabled(SerializationFeature.WRITE_ENUM_KEYS_USING_INDEX)) {
key = String.valueOf(e.ordinal());
} else {
key = e.name();
}
}
g.writeFieldName(key);
}
break;
case TYPE_INTEGER:
case TYPE_LONG:
g.writeFieldId(((Number) value).longValue());
break;
case TYPE_BYTE_ARRAY:
{
String encoded = provider.getConfig().getBase64Variant().encode((byte[]) value);
g.writeFieldName(encoded);
}
break;
case TYPE_TO_STRING:
default:
g.writeFieldName(value.toString());
}
}
}
public static class Dynamic extends StdSerializer<Object>
{
protected transient PropertySerializerMap _dynamicSerializers;
public Dynamic() {
super(String.class, false);
_dynamicSerializers = PropertySerializerMap.emptyForProperties();
}
Object readResolve() {
_dynamicSerializers = PropertySerializerMap.emptyForProperties();
return this;
}
@Override
public void serialize(Object value, JsonGenerator g, SerializerProvider provider)
throws IOException
{
Class<?> cls = value.getClass();
PropertySerializerMap m = _dynamicSerializers;
JsonSerializer<Object> ser = m.serializerFor(cls);
if (ser == null) {
ser = _findAndAddDynamic(m, cls, provider);
}
ser.serialize(value, g, provider);
}
@Override
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException {
visitStringFormat(visitor, typeHint);
}
protected JsonSerializer<Object> _findAndAddDynamic(PropertySerializerMap map,
Class<?> type, SerializerProvider provider) throws JsonMappingException
{
if (type == Object.class) {
JsonSerializer<Object> ser = new Default(Default.TYPE_TO_STRING, type);
_dynamicSerializers = map.newWith(type, ser);
return ser;
}
PropertySerializerMap.SerializerAndMapResult result =
map.findAndAddKeySerializer(type, provider, null);
if (map != result.map) {
_dynamicSerializers = result.map;
}
return result.serializer;
}
}
public static class StringKeySerializer extends StdSerializer<Object>
{
public StringKeySerializer() { super(String.class, false); }
@Override
public void serialize(Object value, JsonGenerator g, SerializerProvider provider) throws IOException {
g.writeFieldName((String) value);
}
}
public static class EnumKeySerializer extends StdSerializer<Object>
{
protected final EnumValues _values;
protected EnumKeySerializer(Class<?> enumType, EnumValues values) {
super(enumType, false);
_values = values;
}
public static EnumKeySerializer construct(Class<?> enumType,
EnumValues enumValues)
{
return new EnumKeySerializer(enumType, enumValues);
}
@Override
public void serialize(Object value, JsonGenerator g, SerializerProvider serializers)
throws IOException
{
if (serializers.isEnabled(SerializationFeature.WRITE_ENUMS_USING_TO_STRING)) {
g.writeFieldName(value.toString());
return;
}
Enum<?> en = (Enum<?>) value;
if (serializers.isEnabled(SerializationFeature.WRITE_ENUM_KEYS_USING_INDEX)) {
g.writeFieldName(String.valueOf(en.ordinal()));
return;
}
g.writeFieldName(_values.serializedValueFor(en));
}
}
}