使用嵌套类作为@RequestBody发送Post请求时出现Bad Request问题排查
嵌套类作为@RequestBody报Bad Request问题排查与解决
问题描述
使用嵌套类作为@RequestBody发送Post请求时返回Bad Request,首次使用嵌套类作为请求体,不确定是JSON格式错误、配置遗漏还是实现方式问题。
实体类代码
@Getter @Builder @AllArgsConstructor public class CreateOrder { @NotNull private final String recipientName; @NotNull private final OrderAddress address; @NotNull private final List<OrderItem> items; @Getter @Builder @AllArgsConstructor public static class OrderItem{ @NotNull private final Product product; @NotNull private final int quantity; } @Getter @Builder @AllArgsConstructor public static class Product{ @NotNull private final Integer id; } }
控制器代码
@RestController @RequiredArgsConstructor @RequestMapping("api/v1/orders") public class OrderController { private final OrderService orderService; @PostMapping public ResponseEntity<Data<CreateOrderResponse>> createOrder(@RequestBody CreateOrder createOrder){ return new ResponseEntity<>(new Data<>(orderService.createOrder(createOrder)), HttpStatus.CREATED); } @GetMapping("/{orderID}") public ResponseEntity<Data<GetOrderResponse>> getOrder(@PathVariable("orderID")UUID orderID){ return new ResponseEntity<>(new Data<>(orderService.getOrder(orderID)), HttpStatus.OK); } }
请求JSON
{ "recipientName": "TEST", "address": { "street": "Street AB", "city": "City A", "postalCode": "30001", "detail": "Block A" }, "items": [ { "product": { "id": 1 }, "quantity": 20 } ] }
问题排查与解决方案
1. 核心问题:缺失OrderAddress类定义
CreateOrder中声明了OrderAddress address字段,但未提供该类的实现,Jackson无法反序列化JSON中的address对象,直接导致参数校验失败,返回Bad Request。
解决:补充OrderAddress静态内部类
在CreateOrder中添加对应的嵌套类,保持和其他类一致的Lombok注解:
@Getter @Builder @AllArgsConstructor @Jacksonized // 配合Jackson反序列化Builder模式 public static class OrderAddress { @NotNull private final String street; @NotNull private final String city; @NotNull private final String postalCode; private final String detail; // 若允许为空可去掉@NotNull }
2. Jackson与Lombok Builder兼容性问题
你的实体类均使用@Builder和@AllArgsConstructor,但Jackson默认无法直接识别Builder模式的对象实例化,导致反序列化失败。
解决:添加@Jacksonized注解
给所有使用@Builder的类(包括外层CreateOrder和所有嵌套类)添加@Jacksonized注解(需Lombok 1.18.16及以上版本),让Jackson支持通过Builder创建对象:
@Getter @Builder @AllArgsConstructor @Jacksonized public class CreateOrder { // 原有字段... } @Getter @Builder @AllArgsConstructor @Jacksonized public static class OrderItem{ // 原有字段... } @Getter @Builder @AllArgsConstructor @Jacksonized public static class Product{ // 原有字段... }
3. 开启详细错误排查(可选)
默认Spring仅返回Bad Request,无具体错误信息,可通过以下方式获取详细校验错误:
- 在控制器方法中添加
@Valid和BindingResult:
@PostMapping public ResponseEntity<Data<CreateOrderResponse>> createOrder(@Valid @RequestBody CreateOrder createOrder, BindingResult result){ if(result.hasErrors()){ List<String> errorDetails = result.getFieldErrors().stream() .map(err -> String.format("%s: %s", err.getField(), err.getDefaultMessage())) .collect(Collectors.toList()); // 根据你的Data结构返回错误信息,示例为添加错误列表字段 return new ResponseEntity<>(new Data<>(null, errorDetails), HttpStatus.BAD_REQUEST); } return new ResponseEntity<>(new Data<>(orderService.createOrder(createOrder)), HttpStatus.CREATED); }
4. JSON格式验证
你的请求JSON格式是正确的,只要补全OrderAddress类并解决Jackson兼容性问题,即可正常映射。
内容的提问来源于stack exchange,提问作者Fen
相关产品推荐
相关产品推荐

