gpt4 book ai didi

java - 为 Jackson 自定义解串器抛出带有 HTTP 状态代码的自定义异常

转载 作者:行者123 更新时间:2023-11-30 12:07:02 31 4
gpt4 key购买 nike

我有这个 InstantDesrializer

@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);
}
}

然后在@ControllerAdvice中对应IOException

@ExceptionHandler(IOException.class)
public ResponseEntity<String> handleIOException(IOException e) {
return ResponseEntity.status(422).build();
}

这在我的 DTO 中:

    @NotNull
@JsonDeserialize(using = InstantDeserializer.class)
// @DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
private Instant timestamp;

即使取消注释 @DateTimeFormat,它也不起作用

理想情况下,它应该返回 422 状态。但是,它返回 400。

也许我只是遗漏了一些我无法弄清楚的小东西。

这里建议使用这种方法: Throw custom exception while deserializing the Date field using jackson in java

最佳答案

您的 Controller 方法从未被调用,因为 JSON 正文解析抛出了异常。

  • 您的@ContollerAdvice 未应用,因为未调用 Controller 方法。

  • 您的 handleIOException 方法未被调用,您的 422 状态未应用。

我怀疑这是更详细的情况......

  1. HTTP 请求包含一个 json 正文。

  2. 与请求的@RequestMapping 和其他注释相匹配的 Controller 方法将您的 DTO 类的实例作为参数。

  3. Spring 尝试在调用您的控制方法之前反序列化传入的 json 主体。它必须这样做才能传递 DTO 对象。

  4. 反序列化使用您的自定义反序列化器,它会抛出 IOException。

  5. 此 IOException 发生在之前您的 Controller 方法被调用。事实上,您的 Controller 方法永远不会为此请求调用。

  6. Spring 使用其默认行为处理异常,返回 HTTP 400。Spring 具有非常广泛的 HTTP 400 RFC 7231 概念。

  7. 由于永远不会调用您的 Controller 方法,因此永远不会应用@ControllerAdvice,并且您的@ExceptionHandler 不会看到异常。状态未设置为 422。

我为什么相信这个?

我经常从 Spring 中看到这种行为,我认为这是预期的行为。但我还没有找到文档或阅读源代码来确定。

你能做些什么?

您可能不喜欢的一种简单方法是声明您的 Controller 方法以接受几乎永远不会失败的输入,例如 String。

  • 您负责验证和反序列化输入,并决定要返回的状态和消息。

  • 您调用 Jackson 进行反序列化。使用您的@ExceptionHandler 方法。

  • 好处:您可以返回 Jackson 经常有用的解析错误消息的文本。这些可以帮助客户找出他们的 json 被拒绝的原因。

如果 Spring 提供一种更时尚的方法,一个可以子类化的类,一个特殊的注解,我不会感到惊讶。我没有追求那个。

你应该怎么做?

400 与 422 是我不想提起诉讼的案例。根据您的优先级,最好接受 Spring 的约定。

RFC 7231 状态 400

The 400 (Bad Request) status code indicates that the server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing).

如果 HTTP 状态码警察找你,你可以指着它说“我认为这个输入是客户端错误。”然后争辩说 422 是不合适的,除非你正在服务 WebDAV只是为了让他们失去平衡。

关于java - 为 Jackson 自定义解串器抛出带有 HTTP 状态代码的自定义异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55214077/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com