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

Postman发送POST请求时Jackson反序列化ProductDto报错求助

JSON反序列化错误分析与解决思路

问题描述

Postman发送POST请求时触发JSON解析错误:

无法构造HogeschoolLeiden.IPRWCApp.product.ProductDto实例(尽管存在至少一个构造器):没有int/Int参数的构造器/工厂方法来从数值10进行反序列化;嵌套异常为com.fasterxml.jackson.databind.exc.MismatchedInputException,错误源于OrderItemDto["product"]的引用链。

相关代码

Product实体类

@Entity
@Table(name = "product")
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column(name = "product_name", columnDefinition = "TEXT", nullable = false, unique = true)
    private String productName;

    @Column(name = "product_photo", columnDefinition = "TEXT")
    private String productPhoto;

    @Column(name = "product_prise", columnDefinition = "INT", nullable = false)
    private int productPrise;

    @Column(name = "product_description", columnDefinition = "TEXT")
    private String productDescription;
}

ProductDto类

@Getter
@Setter
public class ProductDto {

    private Long productId;
    private String productName;
    private String productPhoto;
    private int productPrise;
    private String productDescription;
}

OrderItem实体类

@Entity
@Table(name = "ORDER_ITEM")
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class OrderItem {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne(targetEntity = Product.class, fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = "product", referencedColumnName = "id", updatable = false, nullable = false)
    private Product product;

    @Column(name = "quantity", nullable = false)
    private int quantity;

    @CreationTimestamp
    @Column(name = "created_at", nullable = false, updatable = false)
    private Date createdAt;

    @UpdateTimestamp
    @Column(name = "updated_at")
    private Date updatedAt;
    @ManyToOne
    @JoinColumn(name = "order_id", nullable = false)
    private Order orderCart;
}

OrderItemDto类

@Getter
@Setter
public class OrderItemDto {
    private Long id;
    private ProductDto product;
    private int quantity;
    private Date createdAt;
    private Date updatedAt;
    private Order orderCart;
}

OrderItemService类

@Service
@Transactional
@RequiredArgsConstructor
@AllArgsConstructor
@Slf4j
public class OrderItemService {
    @Autowired
    private ProductRepo productRepo;
    @Autowired
    private OrderItemRepo orderItemRepo;
    @Autowired
    private OrderItemMapper orderItemMapper;

    public OrderItemDto addProductToCart(OrderItemDto orderItemDto) {
        OrderItem orderItem = orderItemMapper.toOrderItem(orderItemDto);
//        Product producty = productRepo.findProductById(orderItemDto.getProduct().getProductId());
//        OrderItem orderItem = OrderItem.builder()
//                .product(producty)
//                .quantity(orderItemDto.getQuantity())
//                .appUser(orderItemDto.getAppUser())
//                .build();
        log.info("Saving new Order-Item: {} to the database.", orderItem.getProduct().getId());
        if (orderItem.getProduct().getId() != null) {
            orderItemRepo.save(orderItem);
            return orderItemMapper.toDTO(orderItem);
        }
        throw new ResponseStatusException(
                HttpStatus.BAD_REQUEST,
                "Order-Item with order-id: " + orderItem.getId() + " doesn't exist between products."
        );
    }

    public List<OrderItemDto> getAllOrderItemsDto() {
        List<OrderItem> orderItemList = orderItemRepo.findAll();
        log.info(orderItemList.toString());
        return orderItemMapper.toDTOs(orderItemList);
    }

    public OrderItemDto getOrderItemDto(Long id) {
        OrderItem orderItem = getOrderItem(id);
        return orderItemMapper.toDTO(orderItem);
    }

    private OrderItem getOrderItem(Long id) {
        return orderItemRepo.findById(id).orElseThrow(()->
                new ResponseStatusException(HttpStatus.NOT_FOUND)
        );
    }

    public void deleteOrderItem(Long id){
        if (!orderItemRepo.existsById(id)) {
            throw new ResponseStatusException(
                    HttpStatus.BAD_REQUEST, "No OrderItem found with id: " + id);
        }
        orderItemRepo.deleteById(id);
    }
}

原因分析

核心问题是你发送的POST请求JSON中,product字段传的是单个数值(比如10),但OrderItemDto里的product字段定义为ProductDto类型。Jackson尝试将这个数值直接反序列化为ProductDto对象,但ProductDto没有接收单个int/long类型参数的构造器或工厂方法,因此抛出反序列化不匹配的错误。

举个例子,你可能传递了如下错误格式的JSON:

{
  "product": 10,
  "quantity": 2
}

解决思路

方案1:调整POST请求的JSON格式(适配现有DTO结构)

如果业务需要传递完整的ProductDto对象,JSON必须符合ProductDto的结构,示例如下:

{
  "product": {
    "productId": 10,
    "productName": "示例商品",
    "productPrise": 99,
    // 其他ProductDto字段按需填写
  },
  "quantity": 2,
  "orderCart": {
    // 对应Order对象的结构
  }
}

方案2:修改OrderItemDto字段定义(更贴合业务逻辑)

实际购物车添加商品的场景中,通常只需要传递产品ID即可,无需完整的产品对象。这种情况下推荐修改OrderItemDto:

  1. 将private ProductDto product;替换为private Long productId;
  2. 在Service层通过productId查询对应的Product实体,再组装OrderItem

修改后的OrderItemDto:

@Getter
@Setter
public class OrderItemDto {
    private Long id;
    private Long productId; // 替换原ProductDto字段
    private int quantity;
    private Date createdAt;
    private Date updatedAt;
    private Order orderCart;
}

调整addProductToCart方法逻辑:

public OrderItemDto addProductToCart(OrderItemDto orderItemDto) {
    // 根据productId查询产品,不存在则抛出404
    Product product = productRepo.findById(orderItemDto.getProductId())
            .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "指定产品不存在"));
    
    // 构建OrderItem对象
    OrderItem orderItem = OrderItem.builder()
            .product(product)
            .quantity(orderItemDto.getQuantity())
            .orderCart(orderItemDto.getOrderCart())
            .build();
    
    log.info("Saving new Order-Item: {} to the database.", product.getId());
    orderItemRepo.save(orderItem);
    return orderItemMapper.toDTO(orderItem);
}

方案3:给ProductDto添加单参数构造器(不推荐)

如果坚持要通过数值直接反序列化ProductDto,可以给ProductDto添加接收productId的构造器,但这种方式会让DTO语义模糊,不符合分层设计原则,仅作备选:

@Getter
@Setter
public class ProductDto {
    private Long productId;
    private String productName;
    private String productPhoto;
    private int productPrise;
    private String productDescription;

    // 添加接收productId的构造器
    public ProductDto(Long productId) {
        this.productId = productId;
    }

    // 保留无参构造器(Jackson反序列化需要)
    public ProductDto() {}
}

内容的提问来源于stack exchange,提问作者H. Motsu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 15:40:28