javaspring-bootpostman

No primary or default constructor found for interface java.util.List Rest API Spring boot


I am passing a request body to a POST request on postman similar to this:

 "name":"Mars",
"artifacts":[
   {
      "elements":[
         {
            "name":"carbon",
            "amount":0.5,
            "measurement":"g"
         }
      ],
      "typeName":"typeA"
   },
   {
      "elements":[
         {
            "name":"hydrogen",
            "amount":0.2,
            "measurement":"g"
         }
      ],
      "typeName":"typeB"
   }
]

The create method in the rest controller looks like this.

  @RequestMapping("/create")
  public Planet create(@RequestBody Planet data) {
      Planet mars = planetService.create(data.getName(),data.getArtifacts());
      return mars;

Planet and all its nested objects have a default constructor such as:

public Planet() {}

However, I am not able to create a new planet object because of lack of a default constructor. Please help!

EDIT: Planet class

public class Planet {
@JsonProperty("name")
private String name;
@Field("artifacts")
private List<Artifact> artifacts;

public Planet() {}

public Planet(String name, List<Artifact> artifacts)
{
this.name = name;
this.artifacts = artifacts;
}
//setters and getters

}

Artifact class:

public class Artifact() {
@Field("elements")
private List<Element> elements;
@JsonProperty("typeName")
private String typeName;

public Artifact() {}

public Artifact(String typeName, List<Element> elements)
{
this.typeName = typeName;
this.elements = elements;
}
}

Element class:

public class Element() {
@JsonProperty("elementName")
private String name;
@JsonProperty("amount")
private double amount;
@JsonProperty("measurement")
private String measurement;

public Element() {}

public Element(String name, double amount, String measurement)
{
//assignments
}
}

Solution

  • I don't understand what is the issue you are facing, but i can see an error straight away so guessing that is the issue you are facing, i am going to give you a solution.

    Create a class which matches your json data structure like this :

    Class PlanetData {
        private String name;
        private List<Planet> artifacts;
    
        public PlanetData(String name, List<Planet> artifacts){
            name = name;
            artifacts = artifacts;
        }
    
        // include rest of getters and setters here.
    }
    

    Then your controller should look like this. Basically you needed to put @RequestBody to all the parameters you want to recieve from request JSON. Earlier you only put @RequestBody to name parameter not artifact parameter and since Request Body can be consumed only once, so you need a wrapper class to recieve the complete request body using single @RequestBody annotation.

    @RequestMapping("/create")
      public String create(@RequestBody PlanetData data) {
          Planet mars = planetService.create(data.getName(),data.getArtifacts());
          return mars.toString();
      }
    

    Edit : Looking at the Planet class, it also needs some modification

    public class Planet {
    private String typeName; // key in json should match variable name for proper deserialization or you need to use some jackson annotation to map your json key to your variable name.
    private List<Element> elements;
    
    public Planet() {}
    
    public Planet(String typeName, List<Element> elements)
    {
    this.typeName = typeName;
    this.elements = elements;
    }
    //setters and getters. Remember to change your setters and getter from name to typeName.
    
    }
    

    Hope this solves your issue.