且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

将类从 2 更改为 1 参数时 Spring POST 400 Bad Request Postman

更新时间:2023-01-03 18:32:44

主要问题是 Jackson 无法构造 DTO 的实例.
解决此问题的两种方法:
1.指定默认构造函数:
- 当您指定参数化构造函数时,Java 编译器不会添加 默认构造函数.

The main issue is Jackson unable to construct instance of a DTO.
Two ways to solve this issue:
1. Specify the default constructor:
- when you specify parameterized constructor, then the Java compiler will not add default constructor.

现在您的第一个请求:

curl --location --request POST 'localhost:8080/cart' 
--header 'Content-Type: application/json' 
--data-raw '[
    {
        "productId": "20000010",
        "quantity": 5.0
    },
    {
        "productId": "20000011",
        "quantity": 7.0
    }
]'

抛出错误:

    "timestamp": "2020-04-27T12:08:28.497+0000",
    "status": 500,
    "error": "Internal Server Error",
    "message": "Type definition error: [simple type, class hello.dto.CartItemDTO]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `hello.dto.CartItemDTO` (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
 at [Source: (PushbackInputStream); line: 3, column: 9] (through reference chain: java.util.ArrayList[0])",
    "path": "/cart"

在向 DTO 添加默认构造函数时,一切正常.

on adding default constructor to DTO, everything works fine as expected.

public class CartItemDTO {

    private String productId;
    private Double quantity;

    public CartItemDTO() {
    }

    public CartItemDTO(String productId, Double quantity) {
        this.productId = productId;
        this.quantity = quantity;
    }

    public String getProductId() {
        return productId;
    }

    public Double getQuantity() {
        return quantity;
    }
}

由于 OP 没有 RecommendationDTO 对象,因此只添加 System.out.println 作为输出:

Since OP does not have RecommendationDTO object, adding just System.out.println as output:

[hello.dto.CartItemDTO@145e35d6, hello.dto.CartItemDTO@25df553f]

  1. 仅 DTO 中的 ProductId

public class CartItemDTO {
    private String productId;

    public CartItemDTO() {
    }

    public CartItemDTO(String productId, Double quantity) {
        this.productId = productId;
    }

    public String getProductId() {
        return productId;
    }
}

请求:

curl --location --request POST 'localhost:8080/cart' 
--header 'Content-Type: application/json' 
--data-raw '[
    {
        "productId": "20000010"
    },
    {
        "productId": "20000011"
    }
]'

输出:

[hello.dto.CartItemDTO@42ad1f23, hello.dto.CartItemDTO@777d8eb3]

  1. 解决方案二:需要指示Jackson使用构造函数创建一个dto对象,实例字段如下:

将 DTO 更改为

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;

public class CartItemDTO {

    private String productId;
    private Double quantity;

    @JsonCreator
    public CartItemDTO(@JsonProperty(value = "productId", required = true) String productId,
                       @JsonProperty(value = "quantity", required = true) Double quantity) {
        this.productId = productId;
        this.quantity = quantity;
    }

    public String getProductId() {
        return productId;
    }

    public Double getQuantity() {
        return quantity;
    }
}

或者只有 productId

OR with only productId

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;

public class CartItemDTO {

    private String productId;

    @JsonCreator
    public CartItemDTO(@JsonProperty(value = "productId", required = true) String productId) {
        this.productId = productId;
    }

    public String getProductId() {
        return productId;
    }
}