在Java中使用Jackson反序列化Date字段时引发自定义异常 [英] Throw custom exception while deserializing the Date field using jackson in java
问题描述
DTO:
@Getter
@Setter
@ToString
public class TestDto {
@NotNull
private String id;
@NotNull
@DateTimeFormat(pattern = "YYYY-MM-DD'T'hh:mm:ss.SSSZ")
private Instant timestamp;
}
当我输入此信息时
{"timestamp":"4/23/2018 11:32 PM","id":"132"}
它给出了BAD_REQUEST(应该),但是我想处理这个格式错误的日期并使用我的自定义异常抛出一个异常.
如何添加呢?
由于尚不支持OP请求的功能: https://github.com/FasterXML/jackson-annotations/issues/130
通过对字段timestamp
使用自定义反序列化器,尝试使用更长的方法来做同样的事情
自定义异常类:
import com.fasterxml.jackson.core.JsonProcessingException;
public class MyException extends JsonProcessingException {
public MyException(String message) {
super(message);
}
}
自定义反序列化器类:
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.util.Date;
public class InstantDeserializer extends StdDeserializer<Instant> {
public InstantDeserializer() {
this(null);
}
public InstantDeserializer(Class<?> vc) {
super(vc);
}
private SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-DD'T'hh:mm:ss.SSS'Z'");
@Override
public Instant deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
JsonNode node = jp.getCodec().readTree(jp);
Date date = null;
try {
date = sdf.parse(node.asText());
} catch (Exception e) {
throw new MyException("Instant field deserialization failed");
}
return date.toInstant();
}
}
更新了TestDto类:
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.constraints.NotNull;
import java.time.Instant;
@Getter
@Setter
@ToString
public class TestDto {
@NotNull
private String id;
@NotNull
@JsonDeserialize(using = InstantDeserializer.class)
@DateTimeFormat(pattern = "YYYY-MM-DD'T'hh:mm:ss.SSS'Z'")
private Instant timestamp;
}
无效的输入请求:
{"timestamp":"4/23/2018 11:32 PM","id":"132"}
响应:
{
"timestamp": 1552845180271,
"status": 400,
"error": "Bad Request",
"message": "JSON parse error: Instant field deserialization failed; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Instant field deserialization failed (through reference chain: TestDto[\"timestamp\"])"
}
有效输入请求:
{"timestamp":"2018-04-23T11:32:22.213Z","id":"132"}
响应:
{
"id": "132",
"timestamp": {
"epochSecond": 1514700142,
"nano": 213000000
}
}
如果您不喜欢时间戳记字段反序列化的方式,并且想要更改它,请此 SO帖子将会有所帮助.
DTO:
@Getter
@Setter
@ToString
public class TestDto {
@NotNull
private String id;
@NotNull
@DateTimeFormat(pattern = "YYYY-MM-DD'T'hh:mm:ss.SSSZ")
private Instant timestamp;
}
When I give this input
{"timestamp":"4/23/2018 11:32 PM","id":"132"}
It gives BAD_REQUEST (which it should), but I want to handle this malformed date and throw an exception with my custom exception.
How can I add this?
Since OP requested feature is not supported yet: https://github.com/FasterXML/jackson-annotations/issues/130
Trying to do the same thing with a bit longer approach by using custom deserializer for a field timestamp
Custom exception class:
import com.fasterxml.jackson.core.JsonProcessingException;
public class MyException extends JsonProcessingException {
public MyException(String message) {
super(message);
}
}
Custom Deserializer class:
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.util.Date;
public class InstantDeserializer extends StdDeserializer<Instant> {
public InstantDeserializer() {
this(null);
}
public InstantDeserializer(Class<?> vc) {
super(vc);
}
private SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-DD'T'hh:mm:ss.SSS'Z'");
@Override
public Instant deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
JsonNode node = jp.getCodec().readTree(jp);
Date date = null;
try {
date = sdf.parse(node.asText());
} catch (Exception e) {
throw new MyException("Instant field deserialization failed");
}
return date.toInstant();
}
}
Updated TestDto class:
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.constraints.NotNull;
import java.time.Instant;
@Getter
@Setter
@ToString
public class TestDto {
@NotNull
private String id;
@NotNull
@JsonDeserialize(using = InstantDeserializer.class)
@DateTimeFormat(pattern = "YYYY-MM-DD'T'hh:mm:ss.SSS'Z'")
private Instant timestamp;
}
Invalid Input request:
{"timestamp":"4/23/2018 11:32 PM","id":"132"}
Response:
{
"timestamp": 1552845180271,
"status": 400,
"error": "Bad Request",
"message": "JSON parse error: Instant field deserialization failed; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Instant field deserialization failed (through reference chain: TestDto[\"timestamp\"])"
}
Valid Input Request:
{"timestamp":"2018-04-23T11:32:22.213Z","id":"132"}
Response:
{
"id": "132",
"timestamp": {
"epochSecond": 1514700142,
"nano": 213000000
}
}
If you do not like the way timestamp field is getting deserialized and would like to change that, this SO post will be helpful.
这篇关于在Java中使用Jackson反序列化Date字段时引发自定义异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!