gwt-jackson
gwt-jackson copied to clipboard
Support @JsonCreator for enum classes
Hi! We would like to add support for @JsonCreator annotations in our enumerations. What would be the best way to approach that?
I didn't know that was possible!
What's the use case ?
I added a PR with a test case. SO discussion: https://stackoverflow.com/questions/12468764/jackson-enum-serializing-and-deserializer
A workaround would be to have a custom deserializer for enum type. It works as expected.
Was this ever addressed?
As we were unaware of the limitations of JsonCreator on an enum and unfortunately have used code similar to the below
@JsonCreator
public static MyEnum parse(String value) {
for(final MyEnum me : values()) {
if(me.getSomeValue() == value) {
return me;
}
}
Log.error("Unknown MyEnum:", value);
return UNKNOWN;
}
The main part here is we return UNKNOWN, which is the default value of the enum, if the value coming from the server does not match an enum we have in the system.
We thought @JsonCreator would be our saviour. We thought it had been tested and passed, but I guess we forgot to try "value that the enum doesn't have" and now running into problems.
I have read about putting a custom deserialiser to get around this, but not seen anything about putting a custom deserialiser on an enum anywhere.
We decided to use a workaround, considering a number of enumerations affected.
Here's what you need for the workaround:
Enumeration JSON deserializer
public class GwtCapabilityDeserializer extends JsonDeserializer<Capability> {
private static final GwtCapabilityDeserializer INSTANCE = new GwtCapabilityDeserializer();
/**
* @return an instance of {@link GwtCapabilityDeserializer}
*/
public static GwtCapabilityDeserializer getInstance() {
return INSTANCE;
}
private GwtCapabilityDeserializer() {
}
@Override
protected Capability doDeserialize(JsonReader reader, JsonDeserializationContext ctx, JsonDeserializerParameters params) {
return Capability.fromString(reader.nextString());
}
}
Key Enumeration JSON Deserializer (optional)
public class GwtProviderTypeKeyDeserializer extends KeyDeserializer<ProviderType> {
private static final GwtProviderTypeKeyDeserializer INSTANCE = new GwtProviderTypeKeyDeserializer();
/**
* @return an instance of {@link GwtProviderTypeKeyDeserializer}
*/
public static GwtProviderTypeKeyDeserializer getInstance() {
return INSTANCE;
}
private GwtProviderTypeKeyDeserializer() {
}
@Override
protected ProviderType doDeserialize(String key, JsonDeserializationContext ctx) {
return ProviderType.get(key);
}
}
CustomDeserializersConfiguration
import com.github.nmorel.gwtjackson.client.AbstractConfiguration;
public class CustomDeserializersConfiguration extends AbstractConfiguration {
@Override
protected void configure() {
// types
type(Capability.class).deserializer(GwtCapabilityDeserializer.class);
// keys
key(ProviderType.class).deserializer(GwtProviderTypeKeyDeserializer.class);
}
}
Update gwt module
<module>
<!-- gwt-jackson dependency -->
<inherits name="com.github.nmorel.gwtjackson.GwtJackson"/>
<inherits name="com.github.nmorel.gwtjackson.guava.GwtJacksonGuava" />
<!-- custom deserializers for gwt-jackson -->
<extend-configuration-property name="gwtjackson.configuration.extension" value="com.example.gwt.serde.CustomDeserializersConfiguration" />
</module>
Ok, when I am back at work on Monday, I will need to give it a try.. But I will admit, I have No idea what any of the code above does or how to use it.
Is there any update on this? I pulled in 0.15.4 to my project but it seems like enums with a static @JsonCreator method are still using the standard enum deserializer. I know it's possible to write a custom one deserializer (and have done so), but would prefer to use the methods specified by our generated model.