JsonMappingException: No suitable constructor found for type [simple type, class ]: can not instantiate from JSON object

JavaJsonSpringAnnotationsJackson

Java Problem Overview


I am getting the following error when trying to get a JSON request and process it:

> org.codehaus.jackson.map.JsonMappingException: No suitable constructor found for type [simple type, class com.myweb.ApplesDO]: can not instantiate from JSON object (need to add/enable type information?)

Here is the JSON I am trying to send:

{
  "applesDO" : [
    {
      "apple" : "Green Apple"
    },
    {
      "apple" : "Red Apple"
    }
  ]
}

In Controller, I have the following method signature:

@RequestMapping("showApples.do")
public String getApples(@RequestBody final AllApplesDO applesRequest){
	// Method Code
}

AllApplesDO is a wrapper of ApplesDO :

public class AllApplesDO {

    private List<ApplesDO> applesDO;

    public List<ApplesDO> getApplesDO() {
        return applesDO;
    }

    public void setApplesDO(List<ApplesDO> applesDO) {
        this.applesDO = applesDO;
    }
}

ApplesDO:

public class ApplesDO {

    private String apple;

    public String getApple() {
        return apple;
    }

    public void setApple(String appl) {
        this.apple = apple;
    }

    public ApplesDO(CustomType custom){
        //constructor Code
    }
}

I think that Jackson is unable to convert JSON into Java objects for subclasses. Please help with the configuration parameters for Jackson to convert JSON into Java Objects. I am using Spring Framework.

EDIT: Included the major bug that is causing this problem in the above sample class - Please look accepted answer for solution.

Java Solutions


Solution 1 - Java

So, finally I realized what the problem is. It is not a Jackson configuration issue as I doubted.

Actually the problem was in ApplesDO Class:

public class ApplesDO {

    private String apple;

    public String getApple() {
        return apple;
    }

    public void setApple(String apple) {
        this.apple = apple;
    }

    public ApplesDO(CustomType custom) {
        //constructor Code
    }
}

There was a custom constructor defined for the class making it the default constructor. Introducing a dummy constructor has made the error to go away:

public class ApplesDO {

    private String apple;

    public String getApple() {
        return apple;
    }

    public void setApple(String apple) {
        this.apple = apple;
    }

    public ApplesDO(CustomType custom) {
        //constructor Code
    }

    //Introducing the dummy constructor
    public ApplesDO() {
    }

}

Solution 2 - Java

This happens for these reasons:

  1. your inner class should be defined as static

    private static class Condition {  //jackson specific    
    }
    
  2. It might be that you got no default constructor in your class (UPDATE: This seems not to be the case)

    private static class Condition {
    	private Long id;
    	
    	public Condition() {
    	}
    
    	// Setters and Getters
    }
    
  3. It could be your Setters are not defined properly or are not visible (e.g. private setter)

Solution 3 - Java

I would like to add another solution to this that does not require a dummy constructor. Since dummy constructors are a bit messy and subsequently confusing. We can provide a safe constructor and by annotating the constructor arguments we allow jackson to determine the mapping between constructor parameter and field.

so the following will also work. Note the string inside the annotation must match the field name.

import com.fasterxml.jackson.annotation.JsonProperty;
public class ApplesDO {

        private String apple;

        public String getApple() {
            return apple;
        }

        public void setApple(String apple) {
            this.apple = apple;
        }

        public ApplesDO(CustomType custom){
            //constructor Code
        }
        
        public ApplesDO(@JsonProperty("apple")String apple) {
        }

}

Solution 4 - Java

When I ran into this problem, it was a result of trying to use an inner class to serve as the DO. Construction of the inner class (silently) required an instance of the enclosing class -- which wasn't available to Jackson.

In this case, moving the inner class to its own .java file fixed the problem.

Solution 5 - Java

Generally, this error comes because we don’t make default constructor.
But in my case:
The issue was coming only due to I have made used object class inside parent class.
This has wasted my whole day.

Solution 6 - Java

Thumb Rule: Add a default constructor for each class you used as a mapping class. You missed this and issue arise!
Simply add default constructor and it should work.

Solution 7 - Java

Can you please test this structure. If I remember correct you can use it this way:

{
    "applesRequest": {
        "applesDO": [
            {
                "apple": "Green Apple"
            },
            {
                "apple": "Red Apple"
            }
        ]
    }
}

Second, please add default constructor to each class it also might help.

Solution 8 - Java

You have to create dummy empty constructor in our model class.So while mapping json, it set by setter method.

Solution 9 - Java

Regarding the last publication I had the same problem where using Lombok 1.18.* generated the problem.

My solution was to add @NoArgsConstructor (constructor without parameters), since @Data includes by default @RequiredArgsConstructor (Constructor with parameters).

lombok Documentation https://projectlombok.org/features/all

That would solve the problem:

package example.counter;

import javax.validation.constraints.NotNull;

import lombok.Data;

@Data
@NoArgsConstructor
public class CounterRequest {
    @NotNull
    private final Integer int1;

    @NotNull
    private final Integer int2;
}

Solution 10 - Java

You must realize what options Jackson has available for deserialization. In Java, method argument names are not present in the compiled code. That's why Jackson can't generally use constructors to create a well-defined object with everything already set.

So, if there is an empty constructor and there are also setters, it uses the empty constructor and setters. If there are no setters, some dark magic (reflections) is used to do it.

If you want to use a constructor with Jackson, you must use the annotations as mentioned by @PiersyP in his answer. You can also use a builder pattern. If you encounter some exceptions, good luck. Error handling in Jackson sucks big time, it's hard to understand that gibberish in error messages.

Solution 11 - Java

If you start annotating constructor, you must annotate all fields.

Notice, my Staff.name field is mapped to "ANOTHER_NAME" in JSON string.

     String jsonInString="{\"ANOTHER_NAME\":\"John\",\"age\":\"17\"}";
     ObjectMapper mapper = new ObjectMapper();
     Staff obj = mapper.readValue(jsonInString, Staff.class);
     // print to screen

     public static class Staff {
       public String name;
       public Integer age;
       public Staff() {	    	
       }	    
       
       //@JsonCreator - don't need this
       public Staff(@JsonProperty("ANOTHER_NAME") String   n,@JsonProperty("age") Integer a) {
    	name=n;age=a;
       }	    
    }

Solution 12 - Java

Add default constructors to all the entity classes

Solution 13 - Java

Failing custom jackson Serializers/Deserializers could also be the problem. Though it's not your case, it's worth mentioning.

I faced the same exception and that was the case.

Solution 14 - Java

For me, this used to work, but upgrading libraries caused this issue to appear. Problem was having a class like this:

package example.counter;

import javax.validation.constraints.NotNull;

import lombok.Data;

@Data
public class CounterRequest {
    @NotNull
    private final Integer int1;

    @NotNull
    private final Integer int2;
}

Using lombok:

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.0</version>
</dependency>

Falling back to

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.16.10</version>
</dependency>

Fixed the issue. Not sure why, but wanted to document it for future.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionLucky MurariView Question on Stackoverflow
Solution 1 - JavaLucky MurariView Answer on Stackoverflow
Solution 2 - JavaazerafatiView Answer on Stackoverflow
Solution 3 - JavaPiersyPView Answer on Stackoverflow
Solution 4 - JavajmarksView Answer on Stackoverflow
Solution 5 - JavaalokView Answer on Stackoverflow
Solution 6 - JavaBadalView Answer on Stackoverflow
Solution 7 - Javadanny.lesnikView Answer on Stackoverflow
Solution 8 - JavaSuresh PatilView Answer on Stackoverflow
Solution 9 - JavaFelipe CeballosView Answer on Stackoverflow
Solution 10 - JavaVlasecView Answer on Stackoverflow
Solution 11 - JavaVortexView Answer on Stackoverflow
Solution 12 - JavaAkash YellappaView Answer on Stackoverflow
Solution 13 - JavaArtem NovikovView Answer on Stackoverflow
Solution 14 - JavaeisView Answer on Stackoverflow