Hi Alex,

I'm +1 generally speaking. Also, I think it's a good idea to hide Jackson
behind Iceberg types, it's a good cleanup (not directly related to Jackson
3).

Reading your points, I have a few comments:
1. About the ordering and "mixing" Jackson 2 and 3, I would do the shims
first (your items 3 and 4) while they are still backed by Jackson 2. We
could deprecate the Jackson typed API in 1.13 (I'm thinking especially
HTTPRequest.mapper() and HTTPClient.Builder.withObjectMapper()). The switch
to Jackson 3 then becomes an internal change, and we ship both Jackson 2
and 3 for a short time. Bundling both is not really a technical problem:
they use different packages, and the Spark/Flink runtime jars already
relocate com.fasterxml, so we just need a tools.jackson relocation. It just
makes the jar bigger and more "exposed" (CVE, etc).
2. Rather than writing new tests, I would parameterize the existing parser
tests (TestSchemaParser, REST request/response parser tests, ...) to run
against both Jackson 2 and Jackson 3 during the transition, They already
cover the JSON contracts. Also, comparing the serialized output of Jackson
2 & 3 would also catch the default feature changes in Jackson 3.
3. I would be very very careful on your point 4, about the REST layer. REST
catalog servers register the serializers on the ObjectMapper. Polaris, for
instance, does that with Quarkus mapper, and Quarkus is moving to Jackson
3. These servers can't avoid Jackson completely: they need a Jackson module
to plug into their mapper. Also, RESTSerializers exposes about 20 public
nested serializer/deserializer classes that extend Jackson types, not only
registerAll(). So I don't think shims alone are enough here. The "separate
artifacts" idea from your first email (and Steve legacy module) fits this
part well. Core would stay binding agnostic, and small adapter modules
(something like iceberg-rest-jackson2 and iceberg-rest-jackson3) would each
expose a Jackson module. Servers pick the one they need.
4. I agree with the splitting. I would suggest:
- introduce the shims and migrate the parsers package by package (several
PRs, I would be happy to help there)
- the REST layer
- dual binding tests and Jackson 3 switch
- removal of the deprecated Jackson 2

Happy to help there!

Regards
JB

On Fri, Nov 6, 2026 at 7:40 PM Alex Dutra via dev <[email protected]>
wrote:

> Hi Steve, hi all,
>
> I played with Steve's suggestion, and I think it's the right
> direction. Here are the main ideas:
>
> 1) Ship both Jackson 2 and Jackson 3 during a transition period. The
> runtime jars would bundle both, until Jackson 2 is removed.
>
> 2) Introduce compatibility tests to verify that the switch carries no
> regressions.
>
> 3) Remove Jackson 2 types from the Json serde layer. This requires
> introducing 2-3 Iceberg-owned shims on top of Jackson types, as Steve
> suggested. The change is mostly mechanical, but touches a lot of
> files.
>
> 4) Remove Jackson 2 types from the REST layer. We'd introduce more
> shims to replace exposure points like RESTSerializers.registerAll()
> and HTTPClient.Builder.withObjectMapper().
>
> Would the community agree on this approach? I think it's a sane one,
> and has the benefit of cleaning up the public API, which is a good
> thing to do anyway.
>
> If so, we just need to figure out how to proceed. The full change
> would touch more than 100 files, especially item 3 above. It's
> certainly possible to split it into a few PRs.
>
> What are your thoughts?
>
> Thanks,
> Alex
>
> On Tue, Jul 28, 2026 at 12:22 PM Steve Loughran <[email protected]>
> wrote:
> >
> >
> > I'd go for
> >
> > leave jackson 2 as is, deprecate, with a goal to cut completely at some
> point
> > accompany an api which hides the json binding,
> > Move to jackson 3 internally, never expose this, either remove the
> jackson 2 apis or move to a iceberg-core-jackson2-legacy module for
> expllicit use and make clear it's only there for one more release
> >
> > Maybe moving the jackson2 stuff to a legacy module from the outset makes
> clear its doomed, but if there's one lesson from OSS, it's "unless you are
> ruthless and make clear it will go, people don't believe you".
> > At then same time: make changes incompatible at the binary level and
> people don't upgrade to your latest release, so don't pick up the latest
> releases, with direct and indirect CVE fixes.
> >
> > On that topic, there's a new jackson 2 release out: no release notes.
> That implies "security fix but they don't want to announce the CVE just yet"
> >
> >
> > On Mon, 27 Jul 2026 at 14:52, Alexandre Dutra <[email protected]> wrote:
> >>
> >> Hi Steve, hi all,
> >>
> >> We discussed this topic briefly in the last sync, in the context of
> >> iceberg-core specifically. Here is a quick summary:
> >>
> >> - The exposure of the Jackson 2 API in iceberg-core often appears
> accidental.
> >>
> >> - If exposure is unavoidable, introducing dual exposure via method
> >> overloads has been proposed.
> >>
> >> - Another option under consideration is providing two separate
> >> artifacts, one for Jackson 2 and one for Jackson 3.
> >>
> >> - Ultimately, we need more time to evaluate the optimal path forward.
> >>
> >> To help guide this decision, I did a deeper investigation into where
> >> these Jackson types actually leak out. The exposure broadly falls into
> >> four categories:
> >>
> >> 1) Parser classes (SchemaParser, MetadataUpdateParser, etc.)
> >> 2) The JsonUtil utility class.
> >> 3) The HTTPRequest.mapper() method.
> >> 4) RESTSerializers.registerAll(ObjectMapper) and
> >> HTTPClient.Builder.withObjectMapper(ObjectMapper).
> >>
> >> Based on these findings, I suggest the following approach for each area:
> >>
> >> - For the parser classes (1), we should ideally restrict visibility to
> >> package-private if feasible (implies revapi exceptions).
> >>
> >> - For JsonUtil (2), I recommend either transitioning it to
> >> package-private or deprecating it for removal.
> >>
> >> - For HTTPRequest.mapper() (3), the exposure was an unfortunate design
> >> choice: we should deprecate it for removal and re-implement the logic
> >> within a package-private helper class.
> >>
> >> Item (4) represents the biggest challenge since consumers legitimately
> >> rely on them to configure their object mappers. Removing them entirely
> >> might be too disruptive; a better approach would be to accept the
> >> tight coupling and introduce parallel Jackson 3 overloads instead. Or,
> >> as Steve mentions, add a layer of indirection to decouple the API
> >> completely.
> >>
> >> In conclusion, if we put the extension points (4) aside for a moment,
> >> it looks like we have a clear opportunity to perform some API cleanup
> >> before we fully commit to the Jackson 3 migration, by reducing the
> >> Jackson 2 exposure to its minimum.
> >>
> >> What do you all think?
> >>
> >> Thanks,
> >> Alex
> >>
> >> On Mon, Jul 20, 2026 at 2:57 PM Steve Loughran <[email protected]>
> wrote:
> >> >
> >> >
> >> > the public APIs are the pain point, and adding jackson 3 overloads is
> possibly going to replicate the same problem.
> >> >
> >> > I'd propose
> >> > - identify those things where json parsing/generation takes place and
> are published
> >> > - see how they could extended such that jackson 3 supported could be
> done without adding jackson 3 to their signatures
> >> >
> >> > I'm thinking of how the various parsers have toJson() methods which
> take jackson generators
> >> >
> >> >   public static void toJson(TableIdentifier identifier, JsonGenerator
> generator)
> >> >
> >> > if another layer of indirection is added (JsonBinding?) that supplied
> the generator then an overridden entry point could be supplied
> >> >
> >> >   public static void toJson(TableIdentifier identifier, JsonBinding
> binding)  {
> >> >    if (binding instance of Jackson2Binding jackson2binding) {
> >> >     return toJson(identifier, jackson2binding.generator());
> >> >    } else {
> >> >      return ((jackson3binding)bindiong)....)
> >> >
> >> > These could be added for the apis today, with the jackson2 stuff
> tagged as deprecated, and new apis only coming though the new overload
> >> >
> >> > I'm glossing over the many implementation details here, but the key
> thing is: exposing someone else's library as part your public API
> inevitably becomes something you end up regretting.
> >> >
> >> >
> >> > On Thu, 16 Jul 2026 at 15:53, Alexandre Dutra <[email protected]>
> wrote:
> >> >>
> >> >> Hi all,
> >> >>
> >> >> As more frameworks (like Spring Boot and Quarkus) migrate to Jackson
> >> >> 3, I wanted to open a conversation about what a Jackson 3 migration
> >> >> would look like for Iceberg and what trade-offs we should think
> >> >> through together.
> >> >>
> >> >> Iceberg currently depends on Jackson 2 in several modules, most
> >> >> significantly iceberg-core. Other modules with direct Jackson
> >> >> dependencies include iceberg-aws, iceberg-nessie, iceberg-snowflake,
> >> >> and iceberg-kafka-connect. Most modules could be migrated separately.
> >> >>
> >> >> The migration is largely mechanical but pervasive: artifact
> >> >> coordinates and Java package names change across the board, several
> >> >> core classes and methods are renamed, ObjectMapper construction moves
> >> >> to a builder pattern, and exceptions become unchecked. JDK 17 is
> >> >> required, which Iceberg already enforces.
> >> >>
> >> >> The blast radius for iceberg-core would be roughly:
> >> >>
> >> >> - Spark and Flink runtime JARs: low impact. Both already shade
> Jackson
> >> >> 2; adding a relocation rule for Jackson 3 is a one-line fix per
> >> >> runtime variant.
> >> >>
> >> >> - Kafka Connect: also low impact, although the Kafka Connect
> >> >> distribution uses unshaded JARs.
> >> >>
> >> >> - Downstream users of iceberg-core: this is the most significant
> >> >> concern. Jackson types leak into the public API of many XYZParser
> >> >> classes, JsonUtil, and the REST HTTP layer.
> >> >>
> >> >> The honest answer is that icebegr-core's public API is permanently
> >> >> Jackson-coupled by design. We should imho acknowledge this fact; the
> >> >> best migration approach is to add Jackson 3 overloads wherever
> >> >> applicable, and make Jackson 2 and 3 coexist for some time.
> >> >>
> >> >> Looking forward to hearing your thoughts on this topic.
> >> >>
> >> >> Thanks,
> >> >> Alex
>

Reply via email to