Java 为Jackson自定义反序列化程序引发带有HTTP状态代码的自定义异常
我有这个InstantDeserializerJava 为Jackson自定义反序列化程序引发带有HTTP状态代码的自定义异常,java,spring,spring-boot,exception,jackson,Java,Spring,Spring Boot,Exception,Jackson,我有这个InstantDeserializer @Slf4j public class InstantDeserializer extends StdDeserializer<Instant> { public InstantDeserializer() { this(null); } public InstantDeserializer(Class<?> vc) { super(vc); }
@Slf4j
public class InstantDeserializer extends StdDeserializer<Instant> {
public InstantDeserializer() {
this(null);
}
public InstantDeserializer(Class<?> vc) {
super(vc);
}
@Override
public Instant deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
JsonNode node = jp.getCodec().readTree(jp);
log.info(node.asText());
TemporalAccessor parse = null;
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(Constants.DATE_TIME_FORMAT).withZone(ZoneOffset.UTC);
try {
parse = dateTimeFormatter.parse(node.asText());
} catch (Exception e) {
e.printStackTrace();
throw new IOException();
}
log.info(Instant.from(parse).toString());
return Instant.from(parse);
}
}
在我的DTO中:
@NotNull
@JsonDeserialize(using = InstantDeserializer.class)
// @DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
private Instant timestamp;
即使是未注释的@DateTimeFormat
,它也不起作用
理想情况下,它应该返回422状态。但是,它返回400
也许我只是错过了一些我无法理解的小事
这里提出了这种方法:
由于JSON正文解析引发异常,因此从未调用控制器方法。
- 由于未调用控制器方法,因此未应用@ContollerAdvice
- 不会调用handleIOException方法,并且不会应用422状态
import com.fasterxml.jackson.core.JsonProcessingException;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
@ResponseStatus(HttpStatus.UNPROCESSABLE_ENTITY)
public class MyException extends JsonProcessingException {
public MyException(String message) {
super(message);
}
}
- 您接管了验证和反序列化输入的责任,并决定返回什么状态和消息
- 你打电话给杰克逊去反序列化。将使用@ExceptionHandler方法
- 好处:您可以返回Jackson常用的解析错误消息的文本。这些可以帮助客户找出他们的json被拒绝的原因
如果HTTP状态码警察找你麻烦,你可以指出这一点并说“我认为这是一个客户端错误。”然后辩称422是不合适的,除非你服务WebDAV只是为了让它们保持平衡。你不需要
handleIOException
方法,只需添加@ResponseStatus即可(HttpStatus.UNPROCESSABLE_实体)
例外
import com.fasterxml.jackson.core.JsonProcessingException;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
@ResponseStatus(HttpStatus.UNPROCESSABLE_ENTITY)
public class MyException extends JsonProcessingException {
public MyException(String message) {
super(message);
}
}
所以当你提出无效的请求时
身躯
{"timestamp":"2018-04-2311:32:22","id":"132"}
答复如下:
{
"timestamp": 1552990867074,
"status": 422,
"error": "Unprocessable Entity",
"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": {
"nano": 213000000,
"epochSecond": 1514700142
}
}
第一个猜测:您之所以获得400,是因为您将json作为post或put的主体发送,您的web服务框架(SpringMVC?)尝试反序列化json但失败。无论原始原因如何,它都会生成400,因为预期的输入无效,这可能发生在将请求路由到代码之前。您的处理程序可能无法看到异常。我建议您在处理程序中设置断点或登录以查看是否调用过它。So、 我添加了日志反序列化程序,日志进入catch语句。您是否登录了处理程序,该处理程序是否被调用过?当Jackson反序列化失败时,您是否希望最终响应中的状态显示为422而不是400?