Reputation: 155
I want to be able to pass in data from a POST request and hit my API in which the JSON I pass through binds to the POTD class. Within POTD, I have an ArrayList of type POTDResources, which is where I am having trouble binding the data.
I'm eventually just going to use the entire Problem
object, but for right now I am just testing with two fields within the class.
I need the JSON input to be able to bind to an ArrayList
of type POTDResources
I'm passing in data like the following:
{
"problemTitle": "Balancing Binary Tree",
"resources": [{"name": "youtube", "link": "http://yotube.com"}]
}
The API call first hits:
@RequestMapping(value = "/generatepotd", method = RequestMethod.POST)
@ResponseBody
public void generatePOTD(@RequestBody POTD problem) throws IOException {
POTD prob = new POTD();
prob.setProblemTitle(problem.getProblemTitle());
prob.setResources(problem.getResources());
tempGen.generateProblemOfTheDay(prob);
}
package com.algoq.algoq.models;
import org.springframework.context.annotation.Description;
import java.util.ArrayList;
@Description("Handles the fields required for processing problem of the day")
public class POTD {
private String subject;
private String problemTitle;
private String problemDescription;
private ArrayList<POTDResources> resources;
// POTD(String subject, String problemTitle, String problemDescription, ArrayList<POTDResources> resources) {
POTD(String problemTitle, ArrayList<POTDResources> resources) {
// this.subject = subject;
this.problemTitle = problemTitle;
// this.problemDescription = problemDescription;
this.resources = resources;
}
public POTD() {
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getProblemTitle() {
return problemTitle;
}
public void setProblemTitle(String problemTitle) {
this.problemTitle = problemTitle;
}
public String getProblemDescription() {
return problemDescription;
}
public void setProblemDescription(String problemDescription) {
this.problemDescription = problemDescription;
}
public ArrayList<POTDResources> getResources() {
return resources;
}
public void setResources(ArrayList<POTDResources> resources) {
this.resources = resources;
}
}
package com.algoq.algoq.models;
public class POTDResources {
private String name;
private String link;
public POTDResources(String name, String link) {
this.name = name;
this.link = link;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLink() {
return link;
}
public void setLink(String link) {
this.link = link;
}
}
{
"timestamp": 1513192593064,
"status": 400,
"error": "Bad Request",
"exception": "org.springframework.http.converter.HttpMessageNotReadableException",
"message": "JSON parse error: Can not construct instance of com.algoq.algoq.models.POTDResources: no suitable constructor found, can not deserialize from Object value (missing default constructor or creator, or perhaps need to add/enable type information?); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of com.algoq.algoq.models.POTDResources: no suitable constructor found, can not deserialize from Object value (missing default constructor or creator, or perhaps need to add/enable type information?)\n at [Source: java.io.PushbackInputStream@1710624f; line: 3, column: 17] (through reference chain: com.algoq.algoq.models.POTD[\"resources\"]->java.util.ArrayList[0])",
"path": "/generatepotd"
}
Upvotes: 1
Views: 1062
Reputation: 373
Your problems lies with the error message:
no suitable constructor found
You are overriding the default constructor, and the ObjectMapper can't create an instance of your Model class.
Try to add a default constructor for POTDResources:
public POTDResources() {
}
Jackson, which is used by Spring for JSON and XML processing, can work 2 ways with Object. Constructor and Setter based. If it can find a constructor with the same field names and types, it will try to use that one. If no suitable constructor, then it will try to create an instance of the object, and use setters. You didn't have a suitable constructor and it failed to create the instance.
Upvotes: 2
Reputation: 3839
Your problem is that POTDResources
does not have a default constructor:
public POTDResources() {}
Jackson requires a no-arg constructor.
Upvotes: 1
Reputation: 2371
Add empty constructor to your POTDResources class:
public POTDResources() {}
The reason being that JSON mapper would first try to initialize your class, and only then would apply values to it
Upvotes: 2