Jackson反序列化User类报无构造器错误,加@JsonProperty仍无效如何解决
问题根本原因
- Jackson无法识别你
User类的全参数构造器作为反序列化入口,@AllArgsConstructor默认生成的构造器没有Jackson的@JsonCreator注解,无法被反序列化逻辑识别 - 入参JSON字段和
User类字段的@JsonProperty配置不匹配:入参里的given_name对应你类里的firstName、family_name对应lastName,当前注解配置的字段名完全不匹配 Instant类型字段的反序列化需要额外的JSR310模块支持,默认ObjectMapper没有注册该模块- 你的
fromJson方法没有处理异常,也没有正确返回Optional值 toJson方法存在笔误,lastName错误赋值为firstName的值
分步解决方案
1. 修复User类的构造器和字段映射配置
两种可选方案,推荐用第一种lombok原生配置:
方案A:lombok注解配置(不需要手动写构造器)
修改User类的注解,给全参构造器加@JsonCreator,同时修正字段的JsonProperty和入参匹配:
@Document(collection = "user") @Builder @AllArgsConstructor(onConstructor_ = @JsonCreator) // 关键配置:让lombok生成的构造器带@JsonCreator注解 public class User { @Indexed(unique = true) @JsonProperty("email") public final String email; @JsonProperty("password") public final String password; @JsonProperty("given_name") // 和入参JSON的given_name对应 public final String firstName; @JsonProperty("family_name") // 和入参JSON的family_name对应 public final String lastName; @JsonProperty("gender") public final Gender gender; // 注册时间后端生成,不需要前端传,加@JsonIgnore避免反序列化报错 @JsonIgnore public final Instant registrationTime; public static User createUser( String email, String password, String firstName, String lastName, Gender gender, Instant registrationTime){ return new User(email, password, firstName, lastName, gender, registrationTime); } }
方案B:手动写构造器(不用lombok配置)
如果不想改lombok注解,可以手动写带@JsonCreator的全参构造器:
@JsonCreator public User( @JsonProperty("email") String email, @JsonProperty("password") String password, @JsonProperty("given_name") String firstName, @JsonProperty("family_name") String lastName, @JsonProperty("gender") Gender gender ){ this.email = email; this.password = password; this.firstName = firstName; this.lastName = lastName; this.gender = gender; this.registrationTime = Instant.now(); // 直接在构造器里生成注册时间 }
2. 配置ObjectMapper支持JSR310时间类型
首先引入JSR310模块依赖(Maven为例):
<dependency> <groupId>com.fasterxml.jackson.datatype</groupId> <artifactId>jackson-datatype-jsr310</artifactId> </dependency>
修改ObjectMapper的Bean配置,注册时间模块:
@Bean ObjectMapper getObjectMapper(){ return new ObjectMapper() .registerModule(new JavaTimeModule()) .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); }
3. 修复UserMapper的代码
修正fromJson方法:
public Optional<User> fromJson(ObjectNode jsonUser) { try { User user = objectMapper.treeToValue(jsonUser, User.class); // 如果用方案A的注解,需要手动补全注册时间 User fullUser = User.createUser(user.email, user.password, user.firstName, user.lastName, user.gender, Instant.now()); return Optional.of(fullUser); } catch (JsonProcessingException e) { // 反序列化失败返回空Optional return Optional.empty(); } }
修正toJson方法的笔误,同时移除敏感字段密码:
public JsonNode toJson(User user) { ObjectNode node = objectMapper.createObjectNode(); node.put("email", user.email); // 不要把密码返回给前端,删除密码输出逻辑 node.put("firstName", user.firstName); node.put("lastName", user.lastName); // 修正之前的笔误,原为user.firstName node.put("gender", user.gender.value); node.put("registrationTime", user.registrationTime.toString()); return node; }
4. 可选:枚举类适配
如果你的Gender枚举反序列化报错,给枚举的value字段加@JsonValue注解即可:
public enum Gender { FEMALE("FEMALE"), MALE("MALE"); @JsonValue public final String value; // 省略构造器 }
内容的提问来源于stack exchange,提问作者user9347049
相关产品推荐
相关产品推荐

