Guidance on api vs implemetation dependency on Jackson libraries


I need some guide on whether dependencies on Jackson libraries should be “api” or “implementation” dependencies. The Java library plugin docs say that “public annotation types” should go to the “api” configuration. Does that apply to com.fasterxml.jackson.annotation.JsonIgnore when used in a class like

data class ProcessedDeclaredLicense(
    val spdxExpression: SpdxExpression?

If so, why? Because IMO the annotation is only a hint on how the Jackson implementation should handle this field. Whether it’s being serialized or not when null should have no effect on the API.

So, is this a case the docs refer to as “public annotation types”?

I’m always wondering why there is no description of this in math like language. Here is my shot on this (the shortest possible I can think of that is still precise and not misleading):

Let l be some library that you want to use in your software project p. Let s be an instance of a first-class citizen contained in l. Let t be an instance of a first-class citizen contained in p. If t is exported by p and if t makes use of s in a way that makes s part of the export of t then l must be declared an API dependency by p. Otherwise, l should be declared an implementation dependency by p.

The things that might still be unclear here are the terms first-class citizen and export, which are described more informally as follows:

first-class citizen of a programming language: An abstract notion that is explicitly defined by some programming language; e.g., in Java, the notion of a class, interface, annotation, enumeration, or the notion of a method. In case of strictly typed programming languages, a first-class citizen is usually a separate kind of type in the language’s type system.

Definition export: An instance of a first-class citizen that is made available to be usable externally by some software project p; i.e., usable outside of p.

So, is that a yes or no? :smiley:

Honestly, I’m still unsure. You say an annotation is a first-class citizen. And I guess using an annotation on a public class creates an instance of the annotation at runtime. But is that instance usable externally just because it’s attached to a public class? I would guess not.

l = Jackson
s = @JsonInclude
p = your project
t = ProcessedDeclaredLicense

My answer wasn’t precise about what part of the export means. Java annotations are special in this regard. The whole thing can be reformulated to the question “Do I need s in the classpath in order to compile a first class citizen u that is not in p but that imports t?” Is that a yes or no :wink: (a yes means an API dependency).

You’re somewhat like a politician, always avoiding to answer a question with a clear yes or nor, and without asking a counter question :wink:

But then I’d say it’s a no, i.e. Jackson is an implementation dependency in my example.