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
How to send Date in REST API in POST method
提问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:
步骤如下:
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; } }
定义自定义解串器
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方法的参考。
Define @JsonDeserialize annotation above the variable
@JsonDeserialize(using=LocalDateDeserializer.class) private LocalDate quantityAtDate;
在变量上方定义@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
错误
JsonMappingException
is 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-11
cannot be parsed to a LocalDate
from 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 deserializer
in the bean class.
否则,添加deserializer
bean 类。