Implemented #227
diff --git a/release-notes/VERSION b/release-notes/VERSION
index 14a2330..d795acc 100644
--- a/release-notes/VERSION
+++ b/release-notes/VERSION
@@ -3,6 +3,7 @@
New minor version.
+#227: Allow "generic" Enum serializers, deserializers, via `SimpleModule`
#237: Add `DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY` to optionally
throw `JsonMappingException` on duplicate keys, tree model (`JsonNode`)
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/EnumDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/EnumDeserializer.java
index 32692b2..d83b364 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/EnumDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/EnumDeserializer.java
@@ -89,7 +89,7 @@
}
if (!ctxt.isEnabled(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL)) {
throw ctxt.weirdStringException(name, _resolver.getEnumClass(),
- "value not one of declared Enum instance names");
+ "value not one of declared Enum instance names: "+_resolver.getEnums());
}
}
return result;
diff --git a/src/main/java/com/fasterxml/jackson/databind/module/SimpleDeserializers.java b/src/main/java/com/fasterxml/jackson/databind/module/SimpleDeserializers.java
index 41676be..22cafb9 100644
--- a/src/main/java/com/fasterxml/jackson/databind/module/SimpleDeserializers.java
+++ b/src/main/java/com/fasterxml/jackson/databind/module/SimpleDeserializers.java
@@ -24,6 +24,13 @@
protected HashMap<ClassKey,JsonDeserializer<?>> _classMappings = null;
+ /**
+ * Flag to help find "generic" enum deserializer, if one has been registered.
+ *
+ * @since 2.3
+ */
+ protected boolean _hasEnumDeserializer = false;
+
/*
/**********************************************************
/* Life-cycle, construction and configuring
@@ -46,6 +53,10 @@
_classMappings = new HashMap<ClassKey,JsonDeserializer<?>>();
}
_classMappings.put(key, deser);
+ // [Issue#227]: generic Enum deserializer?
+ if (forClass == Enum.class) {
+ _hasEnumDeserializer = true;
+ }
}
/**
@@ -110,7 +121,16 @@
DeserializationConfig config, BeanDescription beanDesc)
throws JsonMappingException
{
- return (_classMappings == null) ? null : _classMappings.get(new ClassKey(type));
+ if (_classMappings == null) {
+ return null;
+ }
+ JsonDeserializer<?> deser = _classMappings.get(new ClassKey(type));
+ if (deser == null) {
+ if (_hasEnumDeserializer && type.isEnum()) {
+ deser = _classMappings.get(new ClassKey(Enum.class));
+ }
+ }
+ return deser;
}
@Override
diff --git a/src/main/java/com/fasterxml/jackson/databind/util/EnumResolver.java b/src/main/java/com/fasterxml/jackson/databind/util/EnumResolver.java
index 48acc5a..0abd0d9 100644
--- a/src/main/java/com/fasterxml/jackson/databind/util/EnumResolver.java
+++ b/src/main/java/com/fasterxml/jackson/databind/util/EnumResolver.java
@@ -131,6 +131,15 @@
return _enums[index];
}
+ public List<T> getEnums()
+ {
+ ArrayList<T> enums = new ArrayList<T>(_enums.length);
+ for (T e : _enums) {
+ enums.add(e);
+ }
+ return enums;
+ }
+
public Class<T> getEnumClass() { return _enumClass; }
public int lastValidIndex() { return _enums.length-1; }
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/TestEnumDeserialization.java b/src/test/java/com/fasterxml/jackson/databind/deser/TestEnumDeserialization.java
index ae1e5cd..b685476 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/TestEnumDeserialization.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/TestEnumDeserialization.java
@@ -1,5 +1,6 @@
package com.fasterxml.jackson.databind.deser;
+import java.io.IOException;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.Map;
@@ -12,6 +13,7 @@
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
+import com.fasterxml.jackson.databind.module.SimpleModule;
@SuppressWarnings("serial")
public class TestEnumDeserialization
@@ -28,14 +30,14 @@
/**
* Alternative version that annotates which deserializer to use
*/
- @JsonDeserialize(using=DummySerializer.class)
+ @JsonDeserialize(using=DummyDeserializer.class)
enum AnnotatedTestEnum {
JACKSON, RULES, OK;
}
- public static class DummySerializer extends StdDeserializer<Object>
+ public static class DummyDeserializer extends StdDeserializer<Object>
{
- public DummySerializer() { super(Object.class); }
+ public DummyDeserializer() { super(Object.class); }
@Override
public Object deserialize(JsonParser jp, DeserializationContext ctxt)
{
@@ -43,6 +45,16 @@
}
}
+ public static class LcEnumDeserializer extends StdDeserializer<TestEnum>
+ {
+ public LcEnumDeserializer() { super(TestEnum.class); }
+ @Override
+ public TestEnum deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
+ {
+ return TestEnum.valueOf(jp.getText().toUpperCase());
+ }
+ }
+
protected enum EnumWithCreator {
A, B;
@@ -326,10 +338,19 @@
// [Issue#141]: allow mapping of empty String into null
public void testEnumsWithEmpty() throws Exception
{
- final ObjectMapper m = new ObjectMapper();
- m.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true);
- TestEnum result = m.readValue("\"\"", TestEnum.class);
+ final ObjectMapper mapper = new ObjectMapper();
+ mapper.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true);
+ TestEnum result = mapper.readValue("\"\"", TestEnum.class);
assertNull(result);
}
+ public void testGenericEnumDeserialization() throws Exception
+ {
+ final ObjectMapper mapper = new ObjectMapper();
+ SimpleModule module = new SimpleModule("foobar");
+ module.addDeserializer(Enum.class, new LcEnumDeserializer());
+ mapper.registerModule(module);
+ // not sure this is totally safe but...
+ assertEquals(TestEnum.JACKSON, mapper.readValue(quote("jackson"), TestEnum.class));
+ }
}