You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JSON反序列化错误排查:MySQL插入用户记录失败

JSON反序列化错误:无法从数字值构造Role实例的解决方法

报错信息:JSON parse error: Cannot construct instance: no int/Int-argument constructor/factory method to deserialize from Number value

问题代码

Customer.java

@Entity
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Customer {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String firstname;
    private String lastname;
    @Column(unique = true)
    private String email;
    @Column(nullable = false)
    private String password;
    @Column(unique = true, nullable = false)
    private String username;

    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(name = "user_roles",
            joinColumns = @JoinColumn(name = "user_id"),
            inverseJoinColumns = @JoinColumn(name = "role_id"))
    private List<Role> roles;
}

CustomerController.java

@PostMapping("/customer")
public void addCustomer(@RequestBody Customer customer) {
    customerService.createCustomer(customer);
}

CustomerService.java

@Service
public class CustomerService {
    public CustomerService(CustomerRepository customerRepository) {
        this.customerRepository = customerRepository;
    }

    public void createCustomer(Customer customer) {
        customerRepository.save(customer);
    }
}

Role.java

public class Role {

    @Id
    private Long id;

    private String name;

    @ManyToMany(mappedBy = "roles")
    private Set<Customer> customers;
}

请求JSON

{
  "firstname": "John",
  "lastname": "Doe",
  "email": "John@example.com",
  "password": "john",  // 注意:密码需哈希处理,切勿明文存储
  "username": "john123",
  "roles" : [1]
}

错误原因

请求JSON中roles: [1]传递的是角色ID的数字列表,但Customer实体的roles字段是List<Role>类型。Jackson默认会尝试将数字直接实例化Role对象,但Role类没有接受单个数字(ID)的构造方法,也未配置反序列化规则,导致转换失败。


解决方案

方案1:修改请求JSON格式

将角色ID包装成完整的Role对象结构:

{
  "firstname": "John",
  "lastname": "Doe",
  "email": "John@example.com",
  "password": "john",
  "username": "john123",
  "roles" : [{"id": 1}]
}

方案2:给Role类添加带ID的构造方法

给Role类添加接受ID的构造方法,并通过@JsonCreator标记,让Jackson知道如何用数字创建实例:

public class Role {

    @Id
    private Long id;

    private String name;

    @ManyToMany(mappedBy = "roles")
    private Set<Customer> customers;

    // JPA必须保留无参构造方法
    public Role() {}

    // 标记为Jackson的创建方法
    @JsonCreator
    public Role(@JsonProperty("id") Long id) {
        this.id = id;
    }

    // 若未使用@Data,需补充getter/setter
}

方案3:使用DTO分层处理(推荐)

通过DTO接收前端参数,在服务层手动查询并关联角色,更符合分层架构且更安全:

1. 创建CustomerDTO

@Data
public class CustomerDTO {
    private String firstname;
    private String lastname;
    private String email;
    private String password;
    private String username;
    private List<Long> roleIds; // 接收角色ID列表
}

2. 修改Controller

@PostMapping("/customer")
public void addCustomer(@RequestBody CustomerDTO customerDTO) {
    customerService.createCustomer(customerDTO);
}

3. 修改Service逻辑

@Service
public class CustomerService {
    private final CustomerRepository customerRepository;
    private final RoleRepository roleRepository;
    private final PasswordEncoder passwordEncoder; // 注入密码编码器

    public CustomerService(CustomerRepository customerRepository, RoleRepository roleRepository, PasswordEncoder passwordEncoder) {
        this.customerRepository = customerRepository;
        this.roleRepository = roleRepository;
        this.passwordEncoder = passwordEncoder;
    }

    public void createCustomer(CustomerDTO customerDTO) {
        // 查询对应角色实体
        List<Role> roles = roleRepository.findAllById(customerDTO.getRoleIds());
        // 转换为Customer实体并设置参数
        Customer customer = new Customer();
        customer.setFirstname(customerDTO.getFirstname());
        customer.setLastname(customerDTO.getLastname());
        customer.setEmail(customerDTO.getEmail());
        customer.setPassword(passwordEncoder.encode(customerDTO.getPassword())); // 哈希密码
        customer.setUsername(customerDTO.getUsername());
        customer.setRoles(roles);
        // 保存用户
        customerRepository.save(customer);
    }
}

额外注意事项

  • 必须使用PasswordEncoder对密码进行哈希存储,禁止明文保存
  • 确保RoleRepository已正确定义:public interface RoleRepository extends JpaRepository<Role, Long> {}

内容的提问来源于stack exchange,提问作者Mahesh Guduru

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 21:53:23