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

48,882

Solution 1

You need a no-arg constructor and setters, or use @JsonCreator. Easiest thing to do would be just to add the no-arg with setters. Jackson needs the setters when deserializing. For serialization, all that's needed are getters.

EDIT

To keep it immutable, you can use @JsonCreator on the constructor. For example

@JsonCreator
public Thing(@JsonProperty("symbol") String symbol, 
             @JsonProperty("name") String name) {

    this.symbol = symbol;
    this.name = name;
}

See more Jackson Annotations: @JsonCreator demystified

Solution 2

I'm not absolutely positive, but I think this is it.

The way that Jackson wants to work is this: it creates the object using the default (no argument) constructor. Then it uses setters to set each of the instance variables. This may seem like the long way around, but it's really the only way, because Jackson can't really be smart enough to figure out what order to pass the constructor parameters in. So your code has two main issues (well, three, but I'm going to assume that your class was called Stock before you mostly cleaned it up for posting ;-) ).
1. You need a no-argument constructor. From what I know, java provides a default constructor if you don't write one, but as soon as you make any constructor, the default no-argument constructor goes away.
2. You need setters for your instance variables (and making them public isn't good enough, they have to have actual setters). Oh it looks like your instance variables are final, that's not going to work. My favorite way to manage all the copy/pasted setters is to use a library called lombok. Anyway, for now you just need those setters.

Share:
48,882
Eduardo
Author by

Eduardo

Languages: Java, Scala, Kotlin, JavaScript, TypeScript Build Tools: Gradle, SBT Database: Oracle, MySQL, MongoDB Methodologies: Agile, TDD

Updated on June 28, 2020

Comments

  • Eduardo
    Eduardo almost 4 years

    I have a resource with a method like:

    @PUT
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    @Path("/add")
    public Response putThing(Thing thing) {
        try {
            //Do something with Thing object
            return Response.status(HttpStatus.SC_OK).build();
        } catch (Exception e) {
            log.error("Request failed", e);
            return Response.status(HttpStatus.SC_INTERNAL_SERVER_ERROR).build();
        }
    }
    

    Thing:

    public class Thing {
        private final String symbol;
        private final String name;
    
        public Stock(String symbol, String name) {
            this.symbol = symbol;
            this.name = name;
        }
    
        public String getSymbol() {
            return this.symbol;
        }
    
        public String getName() {
            return this.name;
        }
    }
    

    When I make a PUT request like:

    PUT /rest/add HTTP/1.1
    Host: localhost:8135
    Content-Type: application/json
    Cache-Control: no-cache
    
    {"symbol":"some symbol","name":"some name"}
    

    I get the following response:

    No suitable constructor found for type [simple type, class Thing]: can not instantiate from JSON object (missing default constructor or creator, or perhaps need to add/enable type information?)

    Why is Jersey/Jackson not deserializing my JSON object into my POJO?