Spring接口接收JSON无法反序列化Boat对象,表单数据正常求排查
Spring JSON请求体反序列化Boat对象失败问题排查
问题背景
Spring中创建的POST接口/boat/update,使用@RequestBody接收Boat对象时,原始JSON请求体无法完成反序列化,但使用表单数据(form Data)时可以正常工作。
相关代码
实体类Boat
@Document("Boats") @NoArgsConstructor @AllArgsConstructor @Getter @Setter public class Boat{ @Id private String id; private Boolean online; private String boatName; private String lastOnline; private String password; @JsonIgnore @Transient private java.net.InetAddress inetAddress; private String displayAddress; private String displayStatus; public Boat(String boatName, InetAddress inetAddress,Boolean online) { this.online = online; this.boatName = boatName; this.inetAddress = inetAddress; this.displayAddress = inetAddress.getHostAddress(); if(online){ String pattern = "E, dd MMM yyyy HH:mm:ss z"; SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern); simpleDateFormat.setTimeZone(TimeZone.getTimeZone("CST")); this.lastOnline = simpleDateFormat.format(new Date()); } updateDisplayStatus(); } public void updateDisplayStatus(){ if(getOnline()){ setDisplayStatus(BoatStatus.ONLINE.getDisplayText()); }else{ setDisplayStatus(BoatStatus.OFFLINE.getDisplayText()); } } }
接口代码
@PostMapping(path= "/boat/update") public ResponseEntity updateBoat(@RequestBody Boat boat){ boatFacade.updateBoat(boat); return ResponseEntity.ok().build(); }
请求体内容
{ "id":"62ca4f7c5a3e0f1411445065", "online":"false", "boatName":"dfsjkdfsd", "lastOnline":"null", "password":"null", "displayAddress":"10.50.50.50", "displayStatus":"ONLINE" }
POM依赖
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-mongodb</artifactId> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>3.0.0</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.9.2</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web-services</artifactId> </dependency> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>31.1-jre</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>5.2.2</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> </dependencies>
问题原因
- 类型不匹配:JSON请求体中
online字段的值是字符串"false",但实体类中online是Boolean类型。Jackson默认不支持将字符串形式的布尔值转换为Boolean类型;而表单数据提交时,Spring的表单解析器会自动完成字符串到布尔类型的转换,因此可以正常工作。 - null值表示错误:
lastOnline和password字段的值是字符串"null",这会被反序列化为字符串"null"而非null值,虽然这不会直接导致反序列化失败,但不符合JSON规范,可能引发后续业务逻辑问题。
解决方案
方案一:修正JSON请求体格式
将布尔值改为原生布尔类型,null值直接写null(不带引号),修正后的请求体如下:
{ "id":"62ca4f7c5a3e0f1411445065", "online":false, "boatName":"dfsjkdfsd", "lastOnline":null, "password":null, "displayAddress":"10.50.50.50", "displayStatus":"ONLINE" }
方案二:在实体类中配置类型转换支持
如果无法修改请求体格式,可以在online字段上添加Jackson注解,允许字符串与布尔类型的转换:
@JsonProperty("online") @JsonFormat(shape = JsonFormat.Shape.STRING) private Boolean online;
该注解会让Jackson自动将字符串"true"/"false"转换为对应的布尔值。
另外,实体类已经添加了@NoArgsConstructor,满足Jackson反序列化对无参构造的要求,这部分无需调整;POM依赖中spring-boot-starter-web已经包含了Jackson核心依赖,无需额外添加。
内容的提问来源于stack exchange,提问作者Joe
相关产品推荐
相关产品推荐

