HttpMessageNotreadableException
详解与解决方案在 Spring Boot 应用中,当客户端发送 JSON 数据到后端接口时,可能会遇到以下错误:
org.springframework.http.converter.HttpMessageNotReadableException:
JSON parse error: Cannot construct instance of `com.example.MyRequestVO`
(although at least one Creator exists):
no String-argument constructor/factory method to deserialize from String value ('{"key":"value"}')
这个错误表示 Spring 无法将传入的 JSON 数据正确转换成目标 Java 对象,通常是由于 JSON 反序列化失败导致的。
错误示例:使用 @RequestParam
或 String
接收 JSON 数据
@PostMapping("/test")
public String test(@RequestParam String jsonData) { // ❌ 错误方式
// 尝试手动解析 JSON
}
正确方式:使用 @RequestBody
接收 JSON
@PostMapping("/test")
public String test(@RequestBody MyRequestVO request) { // ✅ 正确方式
// Spring 会自动解析 JSON 到 request 对象
}
Jackson 反序列化要求:
@JsonCreator
标注,会导致反序列化失败。错误示例:
public class MyRequestVO {
private String name;
private int age;
public MyRequestVO(String name, int age) { // ❌ 缺少无参构造方法
this.name = name;
this.age = age;
}
}
解决方案:
public MyRequestVO() {} // ✅ 添加无参构造方法
@JsonCreator
标注构造方法@JsonCreator
public MyRequestVO(
@JsonProperty("name") String name,
@JsonProperty("age") int age
) {
this.name = name;
this.age = age;
}
可能情况:
示例:
{
"userName": "John", // Java 类属性可能是 `username`
"age": 30
}
username
,但 JSON 使用 userName
,会导致字段无法映射。解决方案:
@JsonProperty
指定 JSON 字段名public class MyRequestVO {
@JsonProperty("userName")
private String username;
}
@Configuration
public class JacksonConfig {
@Bean
public ObjectMapper objectMapper() {
return new ObjectMapper()
.setPropertyNamingStrategy(PropertyNamingStrategies.LOWER_CAMEL_CASE);
}
}
Jackson 默认使用 setter 方法或字段反射赋值:
final
的,或者没有 setter
方法,会导致赋值失败。错误示例:
public class MyRequestVO {
private final String name; // ❌ final 字段无法赋值
private int age;
// 没有 setter 方法
}
解决方案:
public void setName(String name) {
this.name = name;
}
@JsonCreator
+ @JsonProperty
(适用于不可变对象)@JsonCreator
public MyRequestVO(
@JsonProperty("name") String name,
@JsonProperty("age") int age
) {
this.name = name;
this.age = age;
}
问题 | 解决方案 |
---|---|
错误使用 @RequestParam 接收 JSON |
改用 @RequestBody |
缺少无参构造方法 | 添加无参构造方法 或 使用 @JsonCreator |
JSON 字段名与 Java 属性名不匹配 | 使用 @JsonProperty 或 配置 Jackson 命名策略 |
类不可变(final)或缺少 setter | 提供 setter 或 使用 @JsonCreator 构造方法 |
JSON 格式错误 | 检查 JSON 数据是否合法 |
@RequestBody
接收 JSON\@PostMapping("/user")
public ResponseEntity createUser(@RequestBody UserRequest request) {
// 处理逻辑
return ResponseEntity.ok("Success");
}
@Data // Lombok 自动生成 getter/setter
@NoArgsConstructor // 无参构造方法
@AllArgsConstructor // 全参构造方法
public class UserRequest {
private String username;
private int age;
}
@JsonInclude
控制 JSON 行为@JsonInclude(JsonInclude.Include.NON_NULL) // 忽略 null 字段
public class UserRequest {
private String username;
private Integer age;
}
@Configuration
public class JacksonConfig {
@Bean
public ObjectMapper objectMapper() {
return new ObjectMapper()
.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE)
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
}
}
HttpMessageNotReadableException
通常是由于 JSON 反序列化失败导致的。@RequestBody
接收 JSON?@JsonCreator
?final
限制?@Data
+ @NoArgsConstructor
) + @RequestBody
,避免手动解析 JSON。