JSTEP 4 - FasterXML/jackson-future-ideas GitHub Wiki
(Back to JSTEP page)
Replace checked JsonProcessingException with unchecked JacksonException
Author
Tatu Saloranta (@cowtowncoder)
Version history
- 2024-06-02: update to indicate completion
- 2019-02-10: first skeletal revision
Status
Complete as of Jackson 2.18
Background
Although choice of JsonProcessingException to extend IOException made sense originally, later developments -- in particular, Java 8 Streams and functional approach in general -- have made use of checked exceptions cumbersome for many use cases. And although there are minor benefits to being able to simply let underlying IOExceptions propagate through reading, actual work to catch and rethrow these are streaming API is quite modest (verified by brief investigation to number of actual stream-read methods).
But due to backwards compatibility concerns, change of base exception type has not been possible within 2.x releases.
Now that we are working on 3.0 we can, however, make this change. Compared to alternative of providing alternate subtypes of ObjectMapper, ObjectReader and/or ObjectWriter (ones that do not declare checked exceptions for methods), this leads to simpler API.
Proposal
New shared base exception
It is proposed that we add JacksonException that directly extends RuntimeException.
An alternative would be for it to extend UncheckedIOException (an existing JDK type): problem is that one can only be created if there is an actual IOException to wrap -- and this would only be true for streaming read/write methods, but not for exceptions Jackson itself throws.
Handling of stream-level IOExceptions from reading/writing
One thing to consider when wrapping low-level IOException from InputStream and OutputStream is whether to:
- Throw a new type of subtype of
JacksonException(WrappedIOException), OR - Wrap these as
UncheckedIOExceptions and only make Jackson's "own" exception (thrown by it directly, not by wrapping) be subtypes ofJacksonException
Although both approaches would work, the plan is to go with (1).
Mapping existing exception hierarchy to new hierarchy
First question on mapping is whether to use existing names, and to what degree. At extremes we could:
- Rename everything to optimal names (mostly get rid of "json" in names), or
- Keep all existing exception names, and at most add new types (approach similar to how 2.x developed)
We should probably do something in-between, to try to balance convenience of upgrade (if names remain mostly the same, only import statements need to be changed, see JSTEP-1) with the goal of improving naming in general.
Here are currently proposed changes to naming:
- Streaming:
JsonProcessingException-> replace withJacksonExceptionJacksonExceptionbackported in 2.12 as the direct parent type ofJsonProcessingException
JsonParseException->StreamReadExceptionJsonGenerationException->StreamWriteException
- Databind:
JsonMappingException-> replace withDatabindExceptionDatabindExceptionbackported in 2.12 as the direct parent type ofJsonMappingException
Open Issues
Currently (2.x) only databind-level (JsonMappingException) exceptions contain logical position within decoded/encoded content. But although streaming exceptions can not create such location in 2.x, with 3.0 we can change this through new context object that parser/generators have... so how should we expose such additional information? Perhaps there could/should be co-variant accessors for location information... ?
Relevant implementation issues:
- Streaming:
- https://github.com/FasterXML/jackson-core/issues/640 -- Add
JacksonExceptiontype (complete in 2.12) - https://github.com/FasterXML/jackson-core/issues/661 -- Convert core to not throw
IOExceptions - https://github.com/FasterXML/jackson-core/issues/668 -- Add
JacksonException.Reference(demote fromJsonMappingException)
- https://github.com/FasterXML/jackson-core/issues/640 -- Add
- Databind:
- https://github.com/FasterXML/jackson-databind/issues/2177 -- Change parent type of
JsonProcessingExceptionto beRuntimeException
- https://github.com/FasterXML/jackson-databind/issues/2177 -- Change parent type of
- Other modules:
- Kotlin: https://github.com/FasterXML/jackson-module-kotlin/issues/410 -- no issues, fine as-is?
- Scala: https://github.com/FasterXML/jackson-module-scala/issues/494 -- no issues, fine as-is?