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