Ryan S
Ryan S

Reputation: 155

Binding JSON to Arraylist in Java Spring?

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:

Controller

@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);
}

POTD Class

    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;
        }
    }

POTD Resource Class

    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;
        }
    }

Error Message

{
    "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

Answers (3)

JSONStatham
JSONStatham

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

Nate Vaughan
Nate Vaughan

Reputation: 3839

Your problem is that POTDResources does not have a default constructor:

public POTDResources() {}

Jackson requires a no-arg constructor.

Upvotes: 1

Alex Savitsky
Alex Savitsky

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

Related Questions