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
