| 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; } |
| } |