1

During the last hours I read many StackOverflow questions and articles, but none of the advices helped. What I tried:

  • Add @JsonCreator and @JsonProperty to both Person and Employee classes (link)
  • Add @JsonDeserialize(using = EmployeeDeserialize.class) to Employee class (link)
  • Add Lombok as dependency, set lombok.anyConstructor.addConstructorProperties=true and add @Data / @Value annotation to both Person and Employee classes (link)
  • Finally, I did the deserialization manually:

    String json = "{\"name\": \"Unknown\",\"email\": \"please@work.now\",\"salary\":1}";
    ObjectMapper objectMapper = new ObjectMapper();
    Employee employee = objectMapper.readValue(json, Employee.class);
    

In this way I could deserialize the JSON, but as soon as I started my spring-boot-starter-web project and called

http://localhost:8080/print?name=unknown&email=please@work.now&salary=1

I got the good old BeanInstantiationException

Failed to instantiate [Employee]: No default constructor found

I run out of ideas. Does anybod know why this worked when I did the deserialization manually? And why it throws exception when I call the REST endpoint?

@SpringBootApplication
public class Application {  
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

@RestController
public class EmployeeController {
    @GetMapping("print")
    public void print(Employee employee) {
        System.out.println(employee);
    }
}

public class Person {
    private final String name;
    @JsonCreator
    public Person(@JsonProperty("name") String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
}

public class Employee extends Person {
    private final String email;
    private final int salary;
    @JsonCreator
    public Employee(
            @JsonProperty("name") String name,
            @JsonProperty("email") String email,
            @JsonProperty("salary") int salary) {
        super(name);
        this.email = email;
        this.salary = salary;
    }
    public String getEmail() {
        return email;
    }
    public int getSalary() {
        return salary;
    }
}
Dimnox
  • 441
  • 1
  • 6
  • 13

1 Answers1

0

You’re implementing JSON deserialisation, yet you’re not using any JSON.

Change to use @PostMapping on your controller method and use something like Postman or cURL to send the JSON to your /print endpoint.

Strelok
  • 50,229
  • 9
  • 102
  • 115
  • I think it should work with @GetMapping as well. If I create default constructors in Employee and Person classes, I can call the REST endpoint. So Jackon and Spring somehow do the deserialization automatically, but I don't know how I could override it. – Dimnox Mar 10 '18 at 04:08
  • It’s not using JSON. Jackson is not deserialising your object. – Strelok Mar 11 '18 at 12:18