Saeed Rajabi Saeed Rajabi - 3 months ago 38
Java Question

How to deserialize json to enum with jackson in java?

I have an interface with name Field as below:

public interface Field {

This interface is in the module A.
I have an enum called BField which is in module B and is implemented as below:

public enum BField implements Field {

There is a class named C in the module A as below:

public class C implements Serializable {
private Set<Field> f;

public Set<Field> getF() { return f; }
public void setF(Set<Field> f) { this f = f; }

I have a REST method as below:

@RequestMapping(method=RequestMethod.Post, value="/save")
public void save (@RequestBody C c) {
//save c

I send this JSON object to this method:

"f": ["SOME_FIELD"]

then I get HTTP 400 bad request error code with the following exception log:

abstract types can only be instantiated with additional type

The hierarchy of the modules is module B is dependent to module A. I tried to use @JsonTypeInfo but the dependency between modules works as a limit and does not let me to use BField.class in the @JsonSubTypes annotation for the field f in class C.


At last I find the solution.

  1. I remove <mvc:annotation-driven/> in my context
  2. Add @JsonDeserialize(as = EnumSet.class) annotation for field private Set<Field> f; in class C.
  3. create a class called JsonBFieldDeserializer in module B as below:

    public class JsonBFieldDeserializer extends StdDeserializer<Field> {
        public JsonBFieldDeserializer() {
        public JsonBFieldDeserializer(Class<?> vc) {
        public Field deserialize(JsonParser jsonParser, DeserializationContext dC) throws IOException, JsonProcessingException {
            JsonNode node = jsonParser.getCodec().readTree();
            String text = node.asText();
            return BField.valueOf(text);
  4. Create a class called BConfiguration in module B as below:

    public class BConfiguration extends WebMVCConfigurationSupport {
        protected void configureMessageConverters(List<HttpMessageConverters<?>> converters){
        MappingJackson2HttpMessageConverter convert(){
            MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
            ObjectMapper objectMapper = new ObjectMapper();
            SimpleModule module = new SimpleModule();
            module.addDeserializer(Field.class, new JsonBFieldDeserializer());
            return converter;
  5. Be careful to use fasterxml jackson not codehaus library!