Java 如何以 POST 方法在 REST API 中发送日期

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/45668936/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 02:06:53  来源:igfitidea点击:

How to send Date in REST API in POST method

javajsonspringrestlocaldate

提问by Amit Gawali

I am trying to build RESTful web service with Spring support. I am getting following exception when I am trying to send POST request.

我正在尝试使用 Spring 支持构建 RESTful Web 服务。当我尝试发送 POST 请求时出现以下异常。

Input:

输入:

POST    http://localhost:8080/InventoryDemo/item

In JSON Payload:

在 JSON 有效负载中:

{"materialId":"ID02","materialName":"Material_2","materialCategory":"LIQUID","currency":"RUPEES","unitCostInCurrency":2200.0,"quantityLevel":1000,"quantityAtDate":"2016-04-11","warehouseName":"WareHouse_2"}

Exception:

例外:

WARNING: Handler execution resulted in exception: Could not read document: Can not instantiate value of type [simple type, class java.time.LocalDate] from String value ('2016-04-11'); no single-String constructor/factory method
 at [Source: java.io.PushbackInputStream@378ace07; line: 1, column: 146] (through reference chain: com.psl.inventory.model.InventorySystemModel["quantityAtDate"]); nested exception is com.fasterxml.Hymanson.databind.JsonMappingException: Can not instantiate value of type [simple type, class java.time.LocalDate] from String value ('2016-04-11'); no single-String constructor/factory method
 at [Source: java.io.PushbackInputStream@378ace07; line: 1, column: 146] (through reference chain: com.psl.inventory.model.InventorySystemModel["quantityAtDate"])

This is my POST method from @RestController:

这是我来自@RestController 的 POST 方法:

@RequestMapping(value = "/item", method = RequestMethod.POST)
    public ResponseEntity<Void> createInventorySystemModel(@RequestBody InventorySystemModel inventorySystemModel,  UriComponentsBuilder ucBuilder) {
        System.out.println("Creating InventorySystemModel " + inventorySystemModel.getMaterialName());

        if (inventorySystemService.isInventorySystemModelExist(inventorySystemModel)) {
            System.out.println("A InventorySystemModel with name " + inventorySystemModel.getMaterialName() + " already exist");
            return new ResponseEntity<Void>(HttpStatus.CONFLICT);
        }

        inventorySystemService.saveInventoryItem(inventorySystemModel);

        HttpHeaders headers = new HttpHeaders();
        headers.setLocation(ucBuilder.path("/user/{materialId}").buildAndExpand(inventorySystemModel.getMaterialId()).toUri());
        return new ResponseEntity<Void>(headers, HttpStatus.CREATED);
    }

and this is my POJO class:

这是我的 POJO 课程:

public class InventorySystemModel {

    private String materialId;
    private String materialName;
    private String materialCategory;
    private String currency;
    private double unitCostInCurrency;
    private int quantityLevel;
    private LocalDate quantityAtDate;
    private String warehouseName;

    public InventorySystemModel(){

    }
    public InventorySystemModel(String materialId, String materialName,
            String materialCategory, String currency,
            double unitCostInCurrency, int quantityLevel, LocalDate quantityAtDate,
            String warehouseName) {
        super();
        this.materialId = materialId;
        this.materialName = materialName;
        this.materialCategory = materialCategory;
        this.currency = currency;
        this.unitCostInCurrency = unitCostInCurrency;
        this.quantityLevel = quantityLevel;
        this.quantityAtDate = quantityAtDate;
        this.warehouseName = warehouseName;
    }

    public String getMaterialId() {
        return materialId;
    }
    public void setMaterialId(String materialId) {
        this.materialId = materialId;
    }
    public String getMaterialName() {
        return materialName;
    }
    public void setMaterialName(String materialName) {
        this.materialName = materialName;
    }
    public String getMaterialCategory() {
        return materialCategory;
    }
    public void setMaterialCategory(String materialCategory) {
        this.materialCategory = materialCategory;
    }
    public String getCurrency() {
        return currency;
    }
    public void setCurrency(String currency) {
        this.currency = currency;
    }
    public double getUnitCostInCurrency() {
        return unitCostInCurrency;
    }
    public void setUnitCostInCurrency(double unitCostInCurrency) {
        this.unitCostInCurrency = unitCostInCurrency;
    }
    public int getQuantityLevel() {
        return quantityLevel;
    }
    public void setQuantityLevel(int quantityLevel) {
        this.quantityLevel = quantityLevel;
    }
    public LocalDate getQuantityAtDate() {
        return quantityAtDate;
    }
    public void setQuantityAtDate(LocalDate quantityAtDate) {
        this.quantityAtDate = quantityAtDate;
    }
    public String getWarehouseName() {
        return warehouseName;
    }
    public void setWarehouseName(String warehouseName) {
        this.warehouseName = warehouseName;
    }
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result
                + ((currency == null) ? 0 : currency.hashCode());
        result = prime
                * result
                + ((materialCategory == null) ? 0 : materialCategory.hashCode());
        result = prime * result
                + ((materialId == null) ? 0 : materialId.hashCode());
        result = prime * result
                + ((materialName == null) ? 0 : materialName.hashCode());
        result = prime * result
                + ((quantityAtDate == null) ? 0 : quantityAtDate.hashCode());
        result = prime * result + quantityLevel;
        long temp;
        temp = Double.doubleToLongBits(unitCostInCurrency);
        result = prime * result + (int) (temp ^ (temp >>> 32));
        result = prime * result
                + ((warehouseName == null) ? 0 : warehouseName.hashCode());
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        InventorySystemModel other = (InventorySystemModel) obj;
        if (currency == null) {
            if (other.currency != null)
                return false;
        } else if (!currency.equals(other.currency))
            return false;
        if (materialCategory == null) {
            if (other.materialCategory != null)
                return false;
        } else if (!materialCategory.equals(other.materialCategory))
            return false;
        if (materialId == null) {
            if (other.materialId != null)
                return false;
        } else if (!materialId.equals(other.materialId))
            return false;
        if (materialName == null) {
            if (other.materialName != null)
                return false;
        } else if (!materialName.equals(other.materialName))
            return false;
        if (quantityAtDate == null) {
            if (other.quantityAtDate != null)
                return false;
        } else if (!quantityAtDate.equals(other.quantityAtDate))
            return false;
        if (quantityLevel != other.quantityLevel)
            return false;
        if (Double.doubleToLongBits(unitCostInCurrency) != Double
                .doubleToLongBits(other.unitCostInCurrency))
            return false;
        if (warehouseName == null) {
            if (other.warehouseName != null)
                return false;
        } else if (!warehouseName.equals(other.warehouseName))
            return false;
        return true;
    }
    @Override
    public String toString() {
        return "InventorySystemModel [materialId=" + materialId
                + ", materialName=" + materialName + ", materialCategory="
                + materialCategory + ", currency=" + currency
                + ", unitCostInCurrency=" + unitCostInCurrency
                + ", quantityLevel=" + quantityLevel + ", quantityAtDate="
                + quantityAtDate + ", warehouseName=" + warehouseName + "]";
    }
}

FYI: I did checked thispost but not getting clue like where exactly I need to do modification.

仅供参考:我确实检查了这篇文章,但没有得到像我需要修改的确切位置的线索。

I am using Java 8 and Spring 4.2

我正在使用 Java 8 和 Spring 4.2

Can some one please explain in detail like what exactly I need to do here. Also I want same date format when I will hit GET request.

有人可以详细解释一下我需要在这里做什么。 当我点击 GET 请求时,我也想要相同的日期格式。

Thanks.

谢谢。

采纳答案by SachinSarawgi

You can make your Custom LocalDateDeserializer. This Deserializer will be called when setter method for the LocalDatevariable is called.

您可以制作自定义LocalDate反序列化器。当调用LocalDate变量的setter 方法时,将调用此反序列化器。

Steps as follows:

步骤如下:

  1. Define a Custom Deserializer

    public class LocalDateDeserializer extends JsonDeserializer<LocalDate>{
    
      @Override
      public LocalDate deserialize(JsonParser p, DeserializationContext ctxt)
            throws IOException, JsonProcessingException {
    
          DateTimeFormatter formatter = DateTimeFormatter.ofPattern("required format");
    
          LocalDate localDate = null;
          localDate = LocalDate.parse(p.getText(), formatter);
    
          return localDate;
      }
    }
    
  1. 定义自定义解串器

    public class LocalDateDeserializer extends JsonDeserializer<LocalDate>{
    
      @Override
      public LocalDate deserialize(JsonParser p, DeserializationContext ctxt)
            throws IOException, JsonProcessingException {
    
          DateTimeFormatter formatter = DateTimeFormatter.ofPattern("required format");
    
          LocalDate localDate = null;
          localDate = LocalDate.parse(p.getText(), formatter);
    
          return localDate;
      }
    }
    

Note: Reference for LocalDate.parsemethod.

注意:LocalDate.parse方法的参考。

  1. Define @JsonDeserialize annotation above the variable

    @JsonDeserialize(using=LocalDateDeserializer.class)
    private LocalDate quantityAtDate;
    
  1. 在变量上方定义@JsonDeserialize 注解

    @JsonDeserialize(using=LocalDateDeserializer.class)
    private LocalDate quantityAtDate;
    

For using @JsonDeserialize annotation import following:

使用@JsonDeserialize 注释导入如下:

import com.fasterxml.Hymanson.databind.annotation.JsonDeserialize;

导入 com.fasterxml.Hymanson.databind.annotation.JsonDeserialize;

Hope this helps.

希望这可以帮助。

回答by Barath

Make use of @JsonFormatto define the date format

使用@JsonFormat定义日期格式

http://www.baeldung.com/Hymanson-serialize-dates

http://www.baeldung.com/Hymanson-serialize-dates

public class InventorySystemModel {

     private String materialId;
        private String materialName;
        private String materialCategory;
        private String currency;
        private double unitCostInCurrency;
        private int quantityLevel;
        @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
        private Date quantityAtDate;
        private String warehouseName;
//getters and setters
}

Request :

要求 :

{
    "materialId": "ID02",
    "materialName": "Material_2",
    "materialCategory": "LIQUID",
    "currency": "RUPEES",
    "unitCostInCurrency": 2200.0,
    "quantityLevel": 1000,
    "quantityAtDate": "2016-04-11",
    "warehouseName": "WareHouse_2"
}

Response :

回复 :

InventorySystemModel [materialId=ID02, materialName=Material_2, materialCategory=LIQUID, currency=RUPEES, unitCostInCurrency=2200.0, quantityLevel=1000, quantityAtDate=Mon Apr 11 05:30:00 IST 2016, warehouseName=WareHouse_2]

回答by cassiomolin

The error

错误

JsonMappingExceptionis an exception thrown by Hymanson, a JSON parser for Java. It indicates fatal problems when mapping a JSON to a Java bean.

JsonMappingException是 Hymanson 抛出的异常,Hymanson 是 Java 的 JSON 解析器。它表示将 JSON 映射到 Java bean 时存在致命问题。

In this situation, looks like the string 2016-04-11cannot be parsed to a LocalDatefrom Java 8.

在这种情况下,该字符串似乎2016-04-11无法LocalDate从 Java 8解析为 a 。

How to fix it

如何修复

Hymanson supports Java 8 date types, but the following dependency is required:

Hymanson 支持 Java 8 日期类型,但需要以下依赖项:

<dependency>
    <groupId>com.fasterxml.Hymanson.datatype</groupId>
    <artifactId>Hymanson-datatype-jsr310</artifactId>
    <version>${Hymanson.version}</version>
</dependency>

And then configure your ObjectMapper:

然后配置你的ObjectMapper

@Configuration
public class HymansonConfig {

    @Bean
    public ObjectMapper createObjectMapper() {  
        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(new JavaTimeModule());
        mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        return mapper;
    }
}

By default, dates will be serialized in the ISO 8601format. If you want to change the format, you can use @JsonFormat:

默认情况下,日期将以ISO 8601格式序列化。如果要更改格式,可以使用@JsonFormat

@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM")
private LocalDate date;

No custom (de)serializers are required.

不需要自定义(反)序列化程序。

回答by Arunchunaivendan

Use a deserializer for parsing the LocalDate.

使用解串器解析 LocalDate。

Add Maven dependency -

添加 Maven 依赖项 -

    <dependency>
        <groupId>com.fasterxml.Hymanson.datatype</groupId>
        <artifactId>Hymanson-datatype-jsr310</artifactId>
        <version>2.8.10</version>
    </dependency>

If your restful service is parsing the bean directly, add the below

如果您的 restful 服务直接解析 bean,请添加以下内容

import com.fasterxml.Hymanson.databind.annotation.JsonDeserialize;
import com.fasterxml.Hymanson.datatype.jsr310.deser.LocalDateDeserializer;

@PostMapping(value = "/xyz")
@JsonDeserialize(using = LocalDateDeserializer.class)
public  ResponseEntity <String> testMethod (@RequestBody Bean bean){
}

Else, add deserializerin the bean class.

否则,添加deserializerbean 类。