Design and distinction of types of Jackson exceptions. #4180
Replies: 1 comment 3 replies
-
Ok, so somewhat condensed answer to much more nuanced question: originally use of But I have since changed my mind about this, partly due exceptions being difficult to handle with Java 8 streams, and similar processing. Now: exception in Jackson 2.x are bit redundant since new types I added for 3.0 --
but since "old" exception cannot be removed during 2.x, this means there are 3 "extra" exception types in hierarchy. Still, eventually renaming should improve readability: exceptions are not JSON-specific, for one, and So, yes, I think that in hindsight it would have made more sense to not base exceptions on Whether parallel hierarchy is useful is actually an interesting question: Jackson 3.0 does actually wrap I hope this helps untangle some aspects of Jackson design. |
Beta Was this translation helpful? Give feedback.
-
This is somewhat in the context of #4165 , for which I soon intend to circle back and help document the API. But I wanted to ask everyone and especially @cowtowncoder some questions about the distinction of Jackson exception types.
In my own core Java library (which has been evolving for over two decades), I'm releasing a version that cleans up a lot of legacy things. Over the years I realized that I've accumulated various "data exception" classes. Some of them are checked. Some of them are unchecked. Some of them descend from
IOException
and some of them don't. Some of them have to do with parsing. Some of them have to do with "syntax" (how that is different from parsing I'm not completely sure). They all seemed like a good idea at the time! 😅So I took a step back and tried to reason from first principles what a "data exception" means, and how it is different from a general "I/O exception". For example, if I try to read a JPEG file and it turns out to be corrupt, is that an error with I/O or an error with the data? I think it can be considered a type of
IOException
. But as you go up the processing layers, it gets murkier whether we are still dealing with "I/O" as such. (You can read all my ponderings about this at JAVA-350, but it's not required reading and maybe not even recommended. hehe)Anyway the concept I seem to be converging on is that, at a certain level, converting the data read from the file to some other type of data is a distinct process from I/O processing, and should result in an exception that is not an
IOException
. This is because, conceptually, I could read in an entire XML file (as an example) and store it in a DOM tree, and it will be sitting in memory. Then if I tried to convert the DOM tree to some object via a mapping function, the data conversion error thrown shouldn't be anIOException
, because no I/O at all was being performed! This is no different than converting a string to something else: I don't suppose anyone would expectInteger.parseInt(String)
to throw anIOException
; similarly,convertXmlToFooBar(Node)
probably shouldn't throw anIOException
either.Following this, just because some
deserialize(…)
method both 1) reads an XML file and 2) maps the DOM to an object in the same method, doesn't to me seem like the mapping suddenly results in anIOException
—it would seem there should still be some distinct exception for data conversion problems. (Or does the fact that the data conversion happens in the same method mean that the data conversion exceptions should be converted to some form ofIOException
?)So I dove into Jackson to see if it aligned with the conceptualization I was forming, and I found that
DatabindException
is used for "all databind level processing problems, as distinct from stream-level problems or I/O issues below". But interestingly,DatabindException
actually ultimately descends fromIOException
!The implication of this is that methods such as
ObjectMapper.treeToValue(TreeNode n, Class<T> valueType)
(which I think is similar to my examples above ofInteger.parseInt(String)
andconvertXmlToFooBar(Node)
), in throwing aJsonProcessingException
, are throwing a type ofIOException
even though in my mindObjectMapper.treeToValue(TreeNode n, Class<T> valueType)
involves no I/O at all. (Maybe it treats a string as anInputStream
internally to reparse something, but to me that doesn't make the method perform I/O as we usually mean.)So @cowtowncoder , I'm curious—did you have a similar quandary about whether to make
JsonProcessingException
and (more to the point)DatabindException
descend fromIOException
or be a completely separate hierarchy of data conversion exceptions? Looking back would you have done it differently? (I'm just curious, and the discussion will help me with decisions I'm making with my libraries.)Beta Was this translation helpful? Give feedback.
All reactions