Джексон, и это страшно IOException - PullRequest
12 голосов
/ 19 сентября 2011

Член Джексона ObjectMapper#readValue выдает три проверенных исключения:

IOException 
JsonParseException 
JsonMappingException

JsonParseException и JsonMappingException удлинение IOException.Я хочу обернуть два вышеупомянутых дочерних класса и выбросить свои собственные исключения, но проверяемый базовый класс IOException требует, чтобы я либо перехватывал, либо выбрасывал его.

Это не делаетдля меня есть смысл подбросить IOException до вызывающего слоя, но, к сожалению, это неприятный запах, если я его скрываю.Моя первоначальная мысль состояла в том, чтобы не перехватить его и передать его механизму исключений для вызывающей / исполняющей среды, чтобы справиться с этим ... пока я не хочу заставлять вызывающую функцию перехватывать или указывать.

Что делать в такой ситуации?

Ответы [ 3 ]

11 голосов
/ 19 сентября 2011

Краткий ответ: если вы имеете дело с IO, вы имеете дело с IOException s.Если вы не имеете дело с IO, то IOException s следует превратить в непроверенные исключения, поскольку они являются признаками ошибочного кода.


Более длинный ответ:

readValue всегда принимает JsonParser, который может быть обернут вокруг ввода-вывода (например, файла или URL).Если вы имеете дело с IO, нет никакого способа обойтись с IOException s, и вы должны либо обработать их, либо отбросить / передать их каким-либо образом.Во время ввода-вывода может произойти что угодно, и вы должны быть готовы справиться с исключениями.

Однако, если вы уверены, что ваши экземпляры JsonParser не используют ввод-вывод (например, вы использовали JsonFactory#createJsonParser(java.lang.String) для созданияJSON-анализатор на строку), вы можете предположить, что любые IOException s, которые вы получаете, являются ошибками, либо в вашем коде, либо в Jackson.Обычно, выбрасывать непроверенное исключение - это правильный способ справиться с ним:

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.");
}

Примечание: моя Java ржавая, и я никогда не использовал Джексона, поэтому рассмотрите приведенный выше блок как псевдокод.

В любом случае вам никогда не нужно объявлять AssertionError в throws, потому что это непроверенные исключения.Все, что является подклассом java.lang.RuntimeException или java.lang.Error, не нужно явно перехватывать или перебрасывать.Эти исключения используются для проблем, которые не должны возникать, если вы не имеете дело с ошибочным кодом или когда хост вашей виртуальной машины горит.

1 голос
/ 20 сентября 2011

Хотя это и не задокументировано в Джексоне, логическое обоснование для исключений IOException является простым: исключения IOException из входных источников (и выходных целей) создаются как есть - поскольку сам Джексон не может ничего сделать для них, они создаются как есть.Единственным дополнительным источником исключений IOException являются вещи, которые концептуально являются частью низкоуровневой (независимой от формата данных) обработки ввода-вывода, в частности, декодирования кодировок символов, таких как UTF-8.

Из этого, кажется, относительноинтуитивно понятно, что JsonParsingException предназначен для проблем, связанных с попыткой разобрать недопустимый контент;и JsonMappingException для проблем на уровне привязки данных.а

1 голос
/ 19 сентября 2011

Вы должны обрабатывать IOException так же, как вы обрабатываете исключения json и переносите их. Поскольку документации Джексона так не хватает, вы действительно не знаете, почему какой-либо из них выбрасывается (за исключением «неизвестной ошибки»).

...