blob: c20897bd33764dfe8d31932c073bf751a3264f74 [file] [log] [blame]
package org.codehaus.jackson.map.ser;
import java.io.*;
import java.util.*;
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.annotate.JsonProperty;
import org.codehaus.jackson.annotate.JsonValue;
import org.codehaus.jackson.map.*;
import org.codehaus.jackson.map.annotate.JsonSerialize;
import org.codehaus.jackson.map.ser.std.ToStringSerializer;
/**
* Unit tests for verifying serialization of simple basic non-structured
* types; primitives (and/or their wrappers), Strings.
*/
public class TestEnumSerialization
extends BaseMapTest
{
/*
/**********************************************************
/* Helper enums
/**********************************************************
*/
/**
* Test enumeration for verifying Enum serialization functionality.
*/
protected enum TestEnum {
A, B, C;
private TestEnum() { }
@Override public String toString() { return name().toLowerCase(); }
}
/**
* Alternative version that forces use of "toString-serializer".
*/
@JsonSerialize(using=ToStringSerializer.class)
protected enum AnnotatedTestEnum {
A2, B2, C2;
private AnnotatedTestEnum() { }
@Override public String toString() { return name().toLowerCase(); }
}
protected enum EnumWithJsonValue {
A("foo"), B("bar");
private final String name;
private EnumWithJsonValue(String n) {
name = n;
}
@JsonValue
@Override
public String toString() { return name; }
}
protected static interface ToStringMixin {
@Override
@JsonValue public String toString();
}
protected enum SerializableEnum implements JsonSerializableWithType
{
A, B, C;
private SerializableEnum() { }
@Override
public void serializeWithType(JsonGenerator jgen, SerializerProvider provider, TypeSerializer typeSer)
throws IOException, JsonProcessingException
{
serialize(jgen, provider);
}
@Override
public void serialize(JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException
{
jgen.writeString("foo");
}
}
protected enum LowerCaseEnum {
A, B, C;
private LowerCaseEnum() { }
@Override
public String toString() { return name().toLowerCase(); }
}
static class MapBean {
public Map<TestEnum,Integer> map = new HashMap<TestEnum,Integer>();
public void add(TestEnum key, int value) {
map.put(key, Integer.valueOf(value));
}
}
// [JACKSON-757]
static enum NOT_OK {
V1("v1");
protected String key;
// any runtime-persistent annotation is fine
NOT_OK(@JsonProperty String key) { this.key = key; }
}
static enum OK {
V1("v1");
protected String key;
OK(String key) { this.key = key; }
}
/*
/**********************************************************
/* Tests
/**********************************************************
*/
public void testSimple() throws Exception
{
ObjectMapper mapper = new ObjectMapper();
StringWriter sw = new StringWriter();
mapper.writeValue(sw, TestEnum.B);
assertEquals("\"B\"", sw.toString());
}
public void testEnumSet() throws Exception
{
ObjectMapper mapper = new ObjectMapper();
StringWriter sw = new StringWriter();
EnumSet<TestEnum> value = EnumSet.of(TestEnum.B);
mapper.writeValue(sw, value);
assertEquals("[\"B\"]", sw.toString());
}
/**
* Whereas regular Enum serializer uses enum names, some users
* prefer calling toString() instead. So let's verify that
* this can be done using annotation for enum class.
*/
public void testEnumUsingToString() throws Exception
{
ObjectMapper mapper = new ObjectMapper();
StringWriter sw = new StringWriter();
mapper.writeValue(sw, AnnotatedTestEnum.C2);
assertEquals("\"c2\"", sw.toString());
}
/**
* Unit test that verifies that standard enum serialization
* can be overridden by using custom serializer factory
* to specify alternative global enum serializer.
*/
public void testEnumUsingCSFEnumOverride() throws Exception
{
ObjectMapper mapper = new ObjectMapper();
CustomSerializerFactory sf = new CustomSerializerFactory();
sf.setEnumSerializer(ToStringSerializer.instance);
mapper.setSerializerFactory(sf);
StringWriter sw = new StringWriter();
mapper.writeValue(sw, TestEnum.B);
assertEquals("\"b\"", sw.toString());
}
/**
* Unit test that verifies that standard enum serialization
* can be overridden by using custom serializer factory
* to specify generic serializer for enum base class
*/
@SuppressWarnings("unchecked")
public void testEnumUsingCSFGenericMapping() throws Exception
{
ObjectMapper mapper = new ObjectMapper();
CustomSerializerFactory sf = new CustomSerializerFactory();
Class<?> enumCls = Enum.class;
sf.addGenericMapping((Class<Object>) enumCls, ToStringSerializer.instance);
mapper.setSerializerFactory(sf);
StringWriter sw = new StringWriter();
mapper.writeValue(sw, TestEnum.A);
assertEquals("\"a\"", sw.toString());
}
// Test [JACKSON-214]
public void testSubclassedEnums() throws Exception
{
ObjectMapper mapper = new ObjectMapper();
assertEquals("\"B\"", mapper.writeValueAsString(EnumWithSubClass.B));
}
// [JACKSON-193]
public void testEnumsWithJsonValue() throws Exception
{
ObjectMapper mapper = new ObjectMapper();
assertEquals("\"bar\"", mapper.writeValueAsString(EnumWithJsonValue.B));
}
// also, for [JACKSON-193], needs to work via mix-ins
public void testEnumsWithJsonValueUsingMixin() throws Exception
{
ObjectMapper mapper = new ObjectMapper();
mapper.getSerializationConfig().addMixInAnnotations(TestEnum.class, ToStringMixin.class);
assertEquals("\"b\"", mapper.writeValueAsString(TestEnum.B));
}
/**
* Test for ensuring that @JsonSerializable is used with Enum types as well
* as with any other types.
*/
public void testSerializableEnum() throws Exception
{
ObjectMapper mapper = new ObjectMapper();
assertEquals("\"foo\"", mapper.writeValueAsString(SerializableEnum.A));
}
// [JACKSON-212]
public void testToStringEnum() throws Exception
{
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationConfig.Feature.WRITE_ENUMS_USING_TO_STRING, true);
assertEquals("\"b\"", mapper.writeValueAsString(LowerCaseEnum.B));
}
// [JACKSON-212]
public void testToStringEnumWithEnumMap() throws Exception
{
ObjectMapper mapper = new ObjectMapper();
EnumMap<LowerCaseEnum,String> m = new EnumMap<LowerCaseEnum,String>(LowerCaseEnum.class);
m.put(LowerCaseEnum.C, "value");
mapper.configure(SerializationConfig.Feature.WRITE_ENUMS_USING_TO_STRING, true);
assertEquals("{\"c\":\"value\"}", mapper.writeValueAsString(m));
}
// [JACKSON-576]
public void testMapWithEnumKeys() throws Exception
{
MapBean bean = new MapBean();
bean.add(TestEnum.B, 3);
String json = new ObjectMapper().writeValueAsString(bean);
assertEquals("{\"map\":{\"b\":3}}", json);
}
// [JACKSON-684]
public void testAsIndex() throws Exception
{
// By default, serialize using name
ObjectMapper mapper = new ObjectMapper();
assertFalse(mapper.isEnabled(SerializationConfig.Feature.WRITE_ENUMS_USING_INDEX));
assertEquals(quote("B"), mapper.writeValueAsString(TestEnum.B));
// but we can change (dynamically, too!) it to be number-based
mapper.enable(SerializationConfig.Feature.WRITE_ENUMS_USING_INDEX);
assertEquals("1", mapper.writeValueAsString(TestEnum.B));
}
// [JACKSON-757]
public void testAnnotationsOnEnumCtor() throws Exception
{
ObjectMapper mapper = new ObjectMapper();
assertEquals(quote("V1"), mapper.writeValueAsString(OK.V1));
assertEquals(quote("V1"), mapper.writeValueAsString(NOT_OK.V1));
assertEquals(quote("V2"), mapper.writeValueAsString(NOT_OK2.V2));
}
}
// [JACKSON-757], non-inner enum
enum NOT_OK2 {
V2("v2");
protected String key;
// any runtime-persistent annotation is fine
NOT_OK2(@JsonProperty String key) { this.key = key; }
}