Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot construct instance of `class name` (although at least on Creator exists)

I have the following class, which I am using as a request payload :

public class SampleRequest {

    private String fromDate;
    private String toDate;

    // Getters and setters removed for brevity.
}

I am trying to use it with this resource below (just trying to print it to screen to see things happen) :

@PostMapping("/getBySignatureOne")
public ResponseEntity<?> getRequestInfo(@Valid @RequestBody SampleRequest signatureOneRequest) {

    System.out.println(signatureOneRequest.getToDate);
    System.out.println(signatureOneRequest.getFromDate);
}

This is the JSON request I send up :

{
    "fromDate":"2019-03-09",
    "toDate":"2019-03-10"
}

This is the error I get :

Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot construct instance of `com.test.app.payload.SampleRequest` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('fromDate'); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `com.test.app.payload.SampleRequest` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('fromDate')
 at [Source: (PushbackInputStream); line: 1, column: 2]]

I'd love to know what's wrong here, I suspect its an issue with constructors, or that I am missing some annotation somewhere, but I am honestly unsure of where I have gone wrong.

like image 282
Slippy Avatar asked Mar 06 '19 21:03

Slippy


3 Answers

You need a constructor with all parameters:

public SampleRequest(String fromDate, String toDate) {

    this.fromDate = fromDate;
    this.toDate = toDate;

}

Or using @AllArgsConstructor or @Data from lombok.

like image 163
Andronicus Avatar answered Nov 02 '22 23:11

Andronicus


Hi you need to write custom deserializer as it not able to parse String (fromDate and toDate) to Date

{ "fromDate":"2019-03-09", "toDate":"2019-03-10" }

this link has a tutorial to get started with custom deserializer https://www.baeldung.com/jackson-deserialization

Deserializer could be written like this.

public class CustomDateDeserializer extends StdDeserializer<Date> {

private static SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");

public CustomDateDeserializer() {
    this(null);
}

public CustomDateDeserializer(Class<?> vc) {
    super(vc);
}

@Override
public Date deserialize(JsonParser jsonparser, DeserializationContext context) throws IOException {
    String date = jsonparser.getText();
    try {
        return formatter.parse(date);
    } catch (ParseException e) {
        throw new RuntimeException(e);
    }
}}

You can register the deserializer at Class itself like this.

@JsonDeserialize(using = ItemDeserializer.class)
public class Item {  ...}

Or either you can register custom deserializer manually like this

ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addDeserializer(Item.class, new ItemDeserializer());
mapper.registerModule(module);
like image 31
dextermini Avatar answered Nov 03 '22 00:11

dextermini


In my case i was missing the No Args contructor

@Data
@AllArgsConstructor
@NoArgsConstructor

for those who are not using Lombok do add no args constructor in the mapping pojo

public ClassA() {
        super();
        // TODO Auto-generated constructor stub
    }

also dont forget to add the Bean of Restemplate in main file if you are using the same

like image 21
Aayush Bhattacharya Avatar answered Nov 03 '22 00:11

Aayush Bhattacharya