杰克逊和那个可怕的IOException

时间:2011-09-19 12:51:20

标签: java json exception jackson convention

Jackson's ObjectMapper#readValue成员抛出三个已检查的例外:

IOException 
JsonParseException 
JsonMappingException

JsonParseExceptionJsonMappingException延长IOException。我想包装前面提到的两个子类并抛出我自己的自定义异常,然而,被检查的基类IOException要求我捕获或抛出它。

IOException扔到调用层是没有意义的,但是,如果我把它隐藏起来,那就是一种气味。我最初的想法是不抓住它并将其留给调用者/运行时异常机制来处理它......但是,我不想强​​迫调用者捕获或指定。

在这种情况下,人们做了什么?

4 个答案:

答案 0 :(得分:11)

简短回答:如果您处理IO,则需要处理IOException。如果你不处理IO,那么IOException应该变成未经检查的异常,因为它们是错误代码的症状。


更长的答案:

readValue总是需要一个JsonParser,它可以包含在IO(例如文件或URL)中。如果您正在处理IO,则无法处理IOException s,您应该处理它们或以某种方式重新抛出/传递它们。在IO期间可能发生任何事情,您应该准备好处理异常。

但是,如果您确定JsonParser实例不使用IO(例如,您使用JsonFactory#createJsonParser(java.lang.String)在字符串上创建JSON解析器),您可以假设任何IOException你收到的是你的代码或杰克逊的错误。通常,抛出未经检查的异常是处理它的正确方法:

ObjectMapper om = new ObjectMapper(/* whatever */);
JsonParser jp = JsonFactory.createJsonParser("{ \"foo\": \"bar\" }");
try {
    return om.readValue(jp);
} catch (IOException e) {
    throw new AssertionError("An IOException occurred when this was assumed to be impossible.");
}

Nota bene:我的Java生锈了,我从未使用过Jackson,所以请考虑上面的块是伪代码。

在任何情况下,您都不需要在AssertionError中声明throws,因为它们是未经检查的例外情况。作为java.lang.RuntimeExceptionjava.lang.Error的子类的所有内容都不需要被明确捕获或重新抛出。这些异常用于预计不会发生的问题,除非您正在处理错误的代码或VM的主机发生故障。

答案 1 :(得分:1)

您应该像处理json异常一样处理IOException并将其包装起来。由于杰克逊的文档缺乏这么多,你真的不知道为什么他们中的任何一个都被抛出(除了“一个未知的错误”)。

答案 2 :(得分:1)

虽然杰克逊没有明确记录这一点,但IOExceptions的基本原理很简单:输入源(和输出目标)的IOExceptions按原样抛出 - 因为杰克逊本身不能为这些做任何事情,所以它们按原样抛出。 IOExceptions的唯一额外来源是概念上属于低级(数据格式无关)I / O处理的东西,特别是UTF-8等字符编码的解码。

从这一点来看,JsonParsingException似乎与尝试解析无效内容相关的问题相对直观;和数据绑定级别的问题的JsonMappingException。 一个

答案 3 :(得分:0)

在 try/catch/rethrow 样板代码中包装十几种方法时,可能会失去耐心。我发现 Lombok 可以为我处理。 希望能帮助到你 https://projectlombok.org/features/SneakyThrows