Implement [JACKSON-834]; add ability for @JsonCreator for enums to accept numbers
diff --git a/release-notes/CREDITS b/release-notes/CREDITS
index 4d75247..4cc71eb 100644
--- a/release-notes/CREDITS
+++ b/release-notes/CREDITS
@@ -907,5 +907,7 @@
Stuart Dootson:
* Reported [Issue-13] Runtime error passing multiple injected values to a constructor
[1.9.7]
-
-
\ No newline at end of file
+
+Klaus Reimer:
+ * [JACKSON-834] Could not use @JsonFactory with non-String argument with Enums
+ [1.9.7]
diff --git a/release-notes/VERSION b/release-notes/VERSION
index da0ee8c..70f8fbb 100644
--- a/release-notes/VERSION
+++ b/release-notes/VERSION
@@ -26,6 +26,8 @@
(reported by James R)
* [JACKSON-832] (partial) Fix numeric range check for Longs (was not working)
(reported by Jan J)
+ * [JACKSON-834] Could not use @JsonFactory with non-String argument with Enums
+ (reported by Klaus R)
------------------------------------------------------------------------
=== History: ===
diff --git a/src/mapper/java/org/codehaus/jackson/map/deser/std/EnumDeserializer.java b/src/mapper/java/org/codehaus/jackson/map/deser/std/EnumDeserializer.java
index 9c06f55..0625ed5 100644
--- a/src/mapper/java/org/codehaus/jackson/map/deser/std/EnumDeserializer.java
+++ b/src/mapper/java/org/codehaus/jackson/map/deser/std/EnumDeserializer.java
@@ -45,13 +45,21 @@
Class<?> enumClass, AnnotatedMethod factory)
{
// note: caller has verified there's just one arg; but we must verify its type
- if (factory.getParameterType(0) != String.class) {
- throw new IllegalArgumentException("Parameter #0 type for factory method ("+factory+") not suitable, must be java.lang.String");
+ Class<?> raw = factory.getParameterClass(0);
+ if (raw == String.class) {
+ raw = null;
+ } else if (raw == Integer.TYPE || raw == Integer.class) {
+ raw = Integer.class;
+ } else if (raw == Long.TYPE || raw == Long.class) {
+ raw = Long.class;
+ } else {
+ throw new IllegalArgumentException("Parameter #0 type for factory method ("+factory
+ +") not suitable, must be java.lang.String or int/Integer/long/Long");
}
if (config.isEnabled(DeserializationConfig.Feature.CAN_OVERRIDE_ACCESS_MODIFIERS)) {
ClassUtil.checkAndFixAccess(factory.getMember());
}
- return new FactoryBasedDeserializer(enumClass, factory);
+ return new FactoryBasedDeserializer(enumClass, factory, raw);
}
/*
@@ -108,26 +116,35 @@
extends StdScalarDeserializer<Object>
{
protected final Class<?> _enumClass;
+
+ // Marker type; null if String expected; otherwise numeric wrapper
+ protected final Class<?> _inputType;
protected final Method _factory;
- public FactoryBasedDeserializer(Class<?> cls, AnnotatedMethod f)
+ public FactoryBasedDeserializer(Class<?> cls, AnnotatedMethod f,
+ Class<?> inputType)
{
super(Enum.class);
_enumClass = cls;
_factory = f.getAnnotated();
+ _inputType = inputType;
}
@Override
public Object deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
- JsonToken curr = jp.getCurrentToken();
-
- // Usually should just get string value:
- if (curr != JsonToken.VALUE_STRING && curr != JsonToken.FIELD_NAME) {
+ // couple of accepted types...
+ Object value;
+ if (_inputType == null) {
+ value = jp.getText();
+ } else if (_inputType == Integer.class) {
+ value = Integer.valueOf(jp.getValueAsInt());
+ } else if (_inputType == Long.class) {
+ value = Long.valueOf(jp.getValueAsLong());
+ } else {
throw ctxt.mappingException(_enumClass);
}
- String value = jp.getText();
try {
return _factory.invoke(_enumClass, value);
} catch (Exception e) {
diff --git a/src/test/org/codehaus/jackson/map/deser/TestEnumDeserialization.java b/src/test/org/codehaus/jackson/map/deser/TestEnumDeserialization.java
index 39a61dd..e7162bc 100644
--- a/src/test/org/codehaus/jackson/map/deser/TestEnumDeserialization.java
+++ b/src/test/org/codehaus/jackson/map/deser/TestEnumDeserialization.java
@@ -57,6 +57,24 @@
@Override
public String toString() { return name().toLowerCase(); }
}
+
+ protected enum TestEnumFor834
+ {
+ ENUM_A(1), ENUM_B(2), ENUM_C(3);
+
+ private final int id;
+
+ private TestEnumFor834(int id) {
+ this.id = id;
+ }
+
+ @JsonCreator public static TestEnumFor834 fromId(int id) {
+ for (TestEnumFor834 e: values()) {
+ if (e.id == id) return e;
+ }
+ return null;
+ }
+ }
/*
/**********************************************************
@@ -222,4 +240,12 @@
new TypeReference<EnumSet<EnumWithCreator>>() {});
assertTrue(value.contains(EnumWithCreator.A));
}
+
+ // [JACKSON-834]
+ public void testEnumsFromInts() throws Exception
+ {
+ ObjectMapper mapper = new ObjectMapper();
+ TestEnumFor834 res = mapper.readValue("1 ", TestEnumFor834.class);
+ assertSame(TestEnumFor834.ENUM_A, res);
+ }
}