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

使用嵌套类作为@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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 14:18:09