没有默认构造函数的SpringBoot反序列化

Posted

技术标签:

【中文标题】没有默认构造函数的SpringBoot反序列化【英文标题】:SpringBoot deserialization without default constructor 【发布时间】:2018-08-18 13:36:27 【问题描述】:

在过去的几个小时里,我阅读了许多 *** 问题和文章,但没有任何建议有帮助。我尝试了什么:

将@JsonCreator 和@JsonProperty 添加到PersonEmployee 类(link) 将@JsonDeserialize(using = EmployeeDeserialize.class) 添加到Employee 类(link) 将 Lombok 添加为依赖项,设置 lombok.anyConstructor.addConstructorProperties=true 并向 PersonEmployee 添加 @Data / @Value 注解类 (link)

最后,我手动进行了反序列化:

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

通过这种方式我可以反序列化 JSON,但是一旦我启动了 spring-boot-starter-web 项目并调用了

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

我得到了很好的旧 BeanInstantiationException

Failed to instantiate [Employee]: No default constructor found

我的想法已经用完了。当我手动进行反序列化时,有人知道为什么这会起作用吗?为什么我调用 REST 端点时会抛出异常?

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

【问题讨论】:

【参考方案1】:

您正在实现 JSON 反序列化,但您没有使用任何 JSON。

更改为在您的控制器方法上使用 @PostMapping 并使用 Postman 或 cURL 之类的东西将 JSON 发送到您的 /print 端点。

【讨论】:

我认为它也应该与 @GetMapping 一起使用。如果我在 Employee 和 Person 类中创建默认构造函数,我可以调用 REST 端点。所以 Jackon 和 Spring 以某种方式自动进行反序列化,但我不知道如何覆盖它。 它没有使用 JSON。 Jackson 没有反序列化您的对象。

以上是关于没有默认构造函数的SpringBoot反序列化的主要内容,如果未能解决你的问题,请参考以下文章

反序列化没有默认构造函数的类型的 STL 容器

使用杰克逊的 JSON 反序列化:没有找到适合类型的构造函数 - 可以提供默认构造函数或注释构造函数 [重复]

Spring Boot:没有从字符串值反序列化的字符串参数构造函数/工厂方法

即使存在默认构造函数,也无法从 Object 值反序列化(没有基于委托或基于属性的 Creator)

Jackson MismatchedInputException(没有从字符串值反序列化的字符串参数构造函数/工厂方法)

Error occurred in deployment step ‘Retract Solution‘: xxx 无法反序列化,因为它没有公共的默认构造函数