jackson-databind: `@JsonValue` with integer for enum does not deserialize correctly
The Javadoc for @JsonValue
states that it is the only required annotation to both serialize and deserialize enums as something other than their name or ordinal:
when use for Java enums, one additional feature is that value returned by annotated method is also considered to be the value to deserialize from, not just JSON String to serialize as. This is possible since set of Enum values is constant and it is possible to define mapping, but can not be done in general for POJO types; as such, this is not used for POJO deserialization.
The Javadoc also states that it can be applied to any scalar type:
Usually value will be of a simple scalar type (String or Number), but it can be any serializable type (Collection, Map or Bean).
However, annotating an enum like below will fail to deserialize – Jackson appears to interpret the integer as the ordinal of the enum.
public enum Type {
A(2),
B(3);
private final int value;
Type(final int value) { this.value = value; }
@JsonValue public int value() { return this.value; }
}
When attempting to deserialize an enum like the above example, on Jackson 2.9.2, I receive the following stack trace: (slightly anonymized)
com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `com.example.Type` from number 3: index value outside legal index range [0..1]
at [Source: (InputStreamReader); line: 1, column: 60] (through reference chain: java.util.ArrayList[0]->com.example.Pojo["type"])
at com.fasterxml.jackson.databind.DeserializationContext.weirdNumberException(DeserializationContext.java:1563)
at com.fasterxml.jackson.databind.DeserializationContext.handleWeirdNumberValue(DeserializationContext.java:953)
at com.fasterxml.jackson.databind.deser.std.EnumDeserializer.deserialize(EnumDeserializer.java:200)
at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeSetAndReturn(MethodProperty.java:149)
If I add a @JsonCreator
to a static method that matches the value to the internal field, the enum can be deserialized correctly. However that is more code I would rather not maintain if possible.
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Reactions: 35
- Comments: 25 (10 by maintainers)
Links to this issue
Commits related to this issue
- Add failing test for #1850 — committed to FasterXML/jackson-databind by cowtowncoder 5 years ago
- Fix Jackson enum Bug Jackson always uses the ordinal number instead of the integer this fix was posted on the comments of the issue regarding this problem: https://github.com/FasterXML/jackson-datab... — committed to tailoric/spring-boot-discord-slashcommand-test by tailoric 3 years ago
- Add credits entry wrt #1850 / #3242 — committed to FasterXML/jackson-databind by cowtowncoder 3 years ago
Hi, I had same issue today, I managed to resolve that using this 2 annotations implemented within my int coded enum:
Hope that helps someone else too, I did spent quite some time to find the variant that works… Cheers 😉
I’ve managed to fix it by setting @JsonCreator mode to DELEGATING and having @JsonValue on my id field e.g.
SOME_VALUE(1), OTHER_VALUE(2)
@JsonValue private Integer id;
Hi. My issue is exactly the same as the one described originally.
I have also recently experienced this and it was certainly a mystery trying to figure it out. In my case it didn’t fail, it just picked the wrong enum (the corresponding ordinal in the enum list) rather than the enum I expected. Very, very confusing.
Yes, I can see how it’s not a common case. If it’s deemed not worthy of inclusion, it might help to clarify the javadocs on
@JsonValue
that the auto-magic deserialization does not work for ints and the client should provide@JsonCreator
as they would normally.