No matching constructor found for type when we use Enum-Jackson JSON

I have a class that looks like this:

   public class Content {

        public enum Type {
            TEXT, URL, FILE
        }

        public enum Rendering {
            MARKDOWN, HTML, PLAIN, AUTO
        }

        public final Type type;
        public final Rendering rendering;
        public final String content;

        public Content(Type type, Rendering rendering, String content) {
            this.type = type;
            this.rendering = (rendering != null ? rendering : Rendering.AUTO);
            this.content = content;
        }

    }

      

And I have a JSON string that looks like this:

{
    "type": "TEXT",
    "rendering": "AUTO",
    "content": "Lorem ipsum"
}

      

Now, since the fields in the class Content

are final Jackson won't work, so I use MixIns :

    public abstract static class ContentMixIn {
        @JsonCreator
        public ContentMixIn(@JsonProperty("type") Type type,
                @JsonProperty("rendering") Rendering rendering,
                @JsonProperty("content") String content) {
        }
    }

      

Note. I could annotate the original class using the constructor parameters, but Content

- from a library that I cannot change

And this is how I use them:

    // ... 
    SimpleModule module = new SimpleModule();
    module.setMixInAnnotation(Content.class, ContentMixIn.class);
    ObjectMapper mapper = new ObjectMapper();
    mapper.registerModule(module);
    mapper.readValue("<the json>", Content.class);

      

This will throw:

com.fasterxml.jackson.databind.JsonMappingException: No suitable constructor found for type [simple type, class com.foo.Content]: can not instantiate from JSON object (need to add/enable type information?)
 at [Source: {
    "type": "TEXT",
    "rendering": "AUTO",
    "content": "Lorem ipsum"
}; line: 2, column: 2]
    at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:148)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1063)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:264)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:124)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3051)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2146)

      

Why? Just by looking at the line number I suppose it is complaining about enum Type

, but how can I fix it?

PS: MixIn is set up correctly, because when I replace my enum paramer constructor with a String value, it works (although not the way I want it):

        // ... in the Content class
        public Content(String type, String rendering, String content) {
            this.type = null;
            this.rendering = null; 
            this.content = content;
        }

        // ... in the mixin class
        @JsonCreator
        public ContentMixIn(@JsonProperty("type") String type,
                            @JsonProperty("rendering") String rendering,
                            @JsonProperty("content") String content) {
        }

      

+3


source to share


1 answer


Basically, I was importing the wrong type, because I was using Intellij and was oblivious when it asked which type to import.

It is extremely important to pay attention to types when working with Jackson.

Special thanks to @Sotirios, he gave me various suggestions on the matter which helped me a lot in debugging. It turns out I have another class that looks like this:



    public static class Image {
        public enum Display {
            COVER, CONTAIN, START, END
        }
        public enum Type {
            BASE64, FILE, URL
        }
        public final Type type; // <-- this!
        public final Display display;
        public final int padding;
        public final String content;

        public Image(Type type, Display display, int padding, String content) {
            this.type = type;
            this.display = display;
            this.padding = padding;
            this.content = content;
        }
    }

      

Jackson failed because I was using Image.Type

MixIn in my class and Content.Type

in my actual class. (They looked the same in code because Intellij was doing static imports)

I also found that you should always use List<T>

JSON ( [...]

) for arrays instead ofT[]

+2


source







All Articles