Merge branch 'jackson3-final-touches'

This commit is contained in:
Reinier Zwitserloot committed 2026-04-22 00:49:54 +02:00
commit 2be766cfc2
12 files changed
+238 -33

No files matched your search

@@ -26,6 +26,9 @@ public enum JacksonVersion implements MappedConfigEnum {
THREE,
;
public static final String AMBIGUOUS_JACKSON_VERSION_WARNING_TEXT =
"Ambiguous: Jackson2 and Jackson3 exist; define which variant(s) you want in 'lombok.config'. See https://projectlombok.org/features/experimental/Jacksonized";
@Override public boolean matches(String value) {
if (this == TWO) return "2".equals(value);
return "3".equals(value);
@@ -453,6 +453,9 @@ public class HandlerUtil {
"com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper",
"com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty",
"com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlText",
"tools.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper",
"tools.jackson.dataformat.xml.annotation.JacksonXmlProperty",
"tools.jackson.dataformat.xml.annotation.JacksonXmlText",
}));
JACKSON_COPY_TO_SETTER_ANNOTATIONS = Collections.unmodifiableList(Arrays.asList(new String[] {
"com.fasterxml.jackson.annotation.JacksonInject",
@@ -467,10 +470,13 @@ public class HandlerUtil {
"com.fasterxml.jackson.annotation.JsonUnwrapped",
"com.fasterxml.jackson.annotation.JsonView",
"com.fasterxml.jackson.databind.annotation.JsonDeserialize",
"tools.jackson.databind.annotation.JsonDeserialize",
"com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper",
"com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty",
"com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlText",
"tools.jackson.databind.annotation.JsonDeserialize",
"tools.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper",
"tools.jackson.dataformat.xml.annotation.JacksonXmlProperty",
"tools.jackson.dataformat.xml.annotation.JacksonXmlText",
}));
JACKSON_COPY_TO_BUILDER_SINGULAR_SETTER_ANNOTATIONS = Collections.unmodifiableList(Arrays.asList(new String[] {
"com.fasterxml.jackson.annotation.JsonAnySetter",
@@ -90,9 +90,11 @@ public class HandleJacksonized extends EclipseAnnotationHandler<Jacksonized> {
return;
}
List<JacksonVersion> jacksonVersions = readConfiguredJacksonVersions(annotationNode);
boolean jacksonizedBuilder = builderAnnotationNode != null || superBuilderAnnotationNode != null;
if (jacksonizedBuilder) {
handleJacksonizedBuilder(ast, annotationNode, annotatedNode, tdNode, td, builderAnnotationNode, superBuilderAnnotationNode);
handleJacksonizedBuilder(ast, annotationNode, annotatedNode, tdNode, td, builderAnnotationNode, superBuilderAnnotationNode, jacksonVersions);
}
if (accessorsAnnotationNode != null) {
@@ -100,7 +102,7 @@ public class HandleJacksonized extends EclipseAnnotationHandler<Jacksonized> {
}
}
private void handleJacksonizedBuilder(Annotation ast, EclipseNode annotationNode, EclipseNode annotatedNode, EclipseNode tdNode, TypeDeclaration td, EclipseNode builderAnnotationNode, EclipseNode superBuilderAnnotationNode) {
private void handleJacksonizedBuilder(Annotation ast, EclipseNode annotationNode, EclipseNode annotatedNode, EclipseNode tdNode, TypeDeclaration td, EclipseNode builderAnnotationNode, EclipseNode superBuilderAnnotationNode, List<JacksonVersion> jacksonVersions) {
boolean isAbstract = (td.modifiers & ClassFileConstants.AccAbstract) != 0;
if (isAbstract) {
annotationNode.addError("Builders on abstract classes cannot be @Jacksonized (the builder would never be used).");
@@ -141,13 +143,6 @@ public class HandleJacksonized extends EclipseAnnotationHandler<Jacksonized> {
ClassLiteralAccess builderClassLiteralAccess = new ClassLiteralAccess(td.sourceEnd, builderClassExpression);
MemberValuePair builderMvp = new MemberValuePair("builder".toCharArray(), td.sourceStart, td.sourceEnd, builderClassLiteralAccess);
List<JacksonVersion> jacksonVersions = annotationNode.getAst().readConfigurationOr(ConfigurationKeys.JACKSONIZED_JACKSON_VERSION, Arrays.<JacksonVersion>asList());
if (jacksonVersions.isEmpty()) {
annotationNode.addWarning("Ambiguous: Jackson2 and Jackson3 exist; define which variant(s) you want in 'lombok.config'. See https://projectlombok.org/features/experimental/Jacksonized");
jacksonVersions = Arrays.asList(JacksonVersion.TWO);
}
if (jacksonVersions.contains(JacksonVersion.TWO)) {
td.annotations = addAnnotation(td, td.annotations, JacksonAnnotationType.JSON_DESERIALIZE2.getQualifiednameAsCharArrayArray(), builderMvp);
}
@@ -193,7 +188,7 @@ public class HandleJacksonized extends EclipseAnnotationHandler<Jacksonized> {
// Add @JsonProperty to all fields. It will be automatically copied to the getter/setters later.
for (EclipseNode eclipseNode : tdNode.down()) {
if (eclipseNode.getKind() == Kind.FIELD) {
if (hasAnnotation(eclipseNode, JacksonAnnotationType.JSON_PROPERTY2) ||
if (hasAnnotation(eclipseNode, JacksonAnnotationType.JSON_PROPERTY2) ||
hasAnnotation(eclipseNode, JacksonAnnotationType.JSON_IGNORE2)) {
continue;
}
@@ -212,7 +207,7 @@ public class HandleJacksonized extends EclipseAnnotationHandler<Jacksonized> {
if (astNode instanceof FieldDeclaration) {
FieldDeclaration fd = (FieldDeclaration) astNode;
StringLiteral fieldName = new StringLiteral(fd.name, 0, 0, 0);
((FieldDeclaration) astNode).annotations = addAnnotation(fieldNode.get(), fd.annotations, JacksonAnnotationType.JSON_PROPERTY2.getQualifiednameAsCharArrayArray(), fieldName);
fd.annotations = addAnnotation(fieldNode.get(), fd.annotations, JacksonAnnotationType.JSON_PROPERTY2.getQualifiednameAsCharArrayArray(), fieldName);
}
}
@@ -220,7 +215,7 @@ public class HandleJacksonized extends EclipseAnnotationHandler<Jacksonized> {
ASTNode astNode = fieldNode.get();
if (astNode instanceof FieldDeclaration) {
FieldDeclaration fd = (FieldDeclaration) astNode;
((FieldDeclaration) astNode).annotations = addAnnotation(fieldNode.get(), fd.annotations, JacksonAnnotationType.JSON_IGNORE2.getQualifiednameAsCharArrayArray());
fd.annotations = addAnnotation(fieldNode.get(), fd.annotations, JacksonAnnotationType.JSON_IGNORE2.getQualifiednameAsCharArrayArray());
}
}
@@ -248,6 +243,13 @@ public class HandleJacksonized extends EclipseAnnotationHandler<Jacksonized> {
return builderClassName;
}
private List<JacksonVersion> readConfiguredJacksonVersions(EclipseNode annotationNode) {
List<JacksonVersion> jacksonVersions = annotationNode.getAst().readConfigurationOr(ConfigurationKeys.JACKSONIZED_JACKSON_VERSION, Arrays.<JacksonVersion>asList());
if (!jacksonVersions.isEmpty()) return jacksonVersions;
annotationNode.addWarning(JacksonVersion.AMBIGUOUS_JACKSON_VERSION_WARNING_TEXT);
return Arrays.asList(JacksonVersion.TWO);
}
private static final Annotation[] EMPTY_ANNOTATIONS_ARRAY = new Annotation[0];
private static Annotation[] findJacksonAnnotationsOnClass(TypeDeclaration td, EclipseNode node) {
@@ -114,9 +114,10 @@ public class HandleJacksonized extends JavacAnnotationHandler<Jacksonized> {
// Add @JsonProperty to all non-transient fields. It will be automatically copied to the getter/setters later.
// Add @JsonIgnore to all transient fields. It will be automatically copied to the getter/setters later.
readConfiguredJacksonVersions(annotationNode);
for (JavacNode javacNode : tdNode.down()) {
if (javacNode.getKind() == Kind.FIELD) {
if (hasAnnotation(javacNode, JacksonAnnotationType.JSON_PROPERTY2) ||
if (hasAnnotation(javacNode, JacksonAnnotationType.JSON_PROPERTY2) ||
hasAnnotation(javacNode, JacksonAnnotationType.JSON_IGNORE2)) {
continue;
}
@@ -131,22 +132,21 @@ public class HandleJacksonized extends JavacAnnotationHandler<Jacksonized> {
private void createJsonPropertyForField(JavacNode fieldNode, JavacNode annotationNode) {
JavacTreeMaker maker = fieldNode.getTreeMaker();
JCExpression jsonPropertyType = chainDots(fieldNode, JacksonAnnotationType.JSON_PROPERTY2);
JCAnnotation annotationJsonProperty = maker.Annotation(jsonPropertyType, List.<JCExpression>of(maker.Literal(fieldNode.getName())));
recursiveSetGeneratedBy(annotationJsonProperty, annotationNode);
JCVariableDecl fieldDecl = ((JCVariableDecl)fieldNode.get());
fieldDecl.mods.annotations = fieldDecl.mods.annotations.append(annotationJsonProperty);
List<JCExpression> args = List.<JCExpression>of(maker.Literal(fieldNode.getName()));
addFieldAnnotation(fieldNode, annotationNode, JacksonAnnotationType.JSON_PROPERTY2, args);
}
private void createJsonIgnoreForField(JavacNode fieldNode, JavacNode annotationNode) {
addFieldAnnotation(fieldNode, annotationNode, JacksonAnnotationType.JSON_IGNORE2, List.<JCExpression>nil());
}
private void addFieldAnnotation(JavacNode fieldNode, JavacNode annotationNode, JacksonAnnotationType annotationType, List<JCExpression> args) {
JavacTreeMaker maker = fieldNode.getTreeMaker();
JCExpression jsonPropertyType = chainDots(fieldNode, JacksonAnnotationType.JSON_IGNORE2);
JCAnnotation annotationJsonProperty = maker.Annotation(jsonPropertyType, List.<JCExpression>nil());
recursiveSetGeneratedBy(annotationJsonProperty, annotationNode);
JCVariableDecl fieldDecl = ((JCVariableDecl)fieldNode.get());
fieldDecl.mods.annotations = fieldDecl.mods.annotations.append(annotationJsonProperty);
JCExpression type = chainDots(fieldNode, annotationType);
JCAnnotation annotation = maker.Annotation(type, args);
recursiveSetGeneratedBy(annotation, annotationNode);
JCVariableDecl fieldDecl = (JCVariableDecl) fieldNode.get();
fieldDecl.mods.annotations = fieldDecl.mods.annotations.append(annotation);
}
private void handleJacksonizedBuilder(JavacNode annotationNode, JavacNode annotatedNode, JavacNode tdNode, JCClassDecl td, JavacNode builderAnnotationNode, JavacNode superBuilderAnnotationNode) {
@@ -191,19 +191,14 @@ public class HandleJacksonized extends JavacAnnotationHandler<Jacksonized> {
return;
}
Collection<JacksonVersion> jacksonVersions = readConfiguredJacksonVersions(annotationNode);
// Insert @JsonDeserialize on annotated class.
if (hasAnnotation(tdNode, JacksonAnnotationType.JSON_DESERIALIZE2) || hasAnnotation(tdNode, JacksonAnnotationType.JSON_DESERIALIZE3)) {
annotationNode.addError("@JsonDeserialize already exists on class. Either delete @JsonDeserialize, or remove @Jacksonized and manually configure Jackson.");
return;
}
Collection<JacksonVersion> jacksonVersions = annotationNode.getAst().readConfigurationOr(ConfigurationKeys.JACKSONIZED_JACKSON_VERSION, Arrays.<JacksonVersion>asList());
if (jacksonVersions.isEmpty()) {
annotationNode.addWarning("Ambiguous: Jackson2 and Jackson3 exist; define which variant(s) you want in 'lombok.config'. See https://projectlombok.org/features/experimental/Jacksonized");
jacksonVersions = Arrays.asList(JacksonVersion.TWO);
}
if (jacksonVersions.contains(JacksonVersion.TWO)) {
JCExpression jsonDeserializeType = chainDots(annotatedNode, JacksonAnnotationType.JSON_DESERIALIZE2);
insertJsonDeserializeAnnotation(annotationNode, annotatedNode, tdNode, td, maker, builderClassName, jsonDeserializeType);
@@ -280,6 +275,13 @@ public class HandleJacksonized extends JavacAnnotationHandler<Jacksonized> {
return builderClassName;
}
private Collection<JacksonVersion> readConfiguredJacksonVersions(JavacNode annotationNode) {
Collection<JacksonVersion> jacksonVersions = annotationNode.getAst().readConfigurationOr(ConfigurationKeys.JACKSONIZED_JACKSON_VERSION, Arrays.<JacksonVersion>asList());
if (!jacksonVersions.isEmpty()) return jacksonVersions;
annotationNode.addWarning(JacksonVersion.AMBIGUOUS_JACKSON_VERSION_WARNING_TEXT);
return Arrays.asList(JacksonVersion.TWO);
}
private static List<JCAnnotation> findJacksonAnnotationsOnClass(JavacNode node) {
ListBuffer<JCAnnotation> result = new ListBuffer<JCAnnotation>();
for (JavacNode child : node.down()) {
@@ -0,0 +1,109 @@
//version 8: Jackson deps are at least Java7+.
//CONF: lombok.jacksonized.jacksonVersion += 3
class JacksonizedAccessorsJackson3 {
@com.fasterxml.jackson.annotation.JsonProperty("name")
private String name;
@com.fasterxml.jackson.annotation.JsonProperty("age")
private int age;
@com.fasterxml.jackson.annotation.JsonIgnore
private transient String password;
@java.lang.SuppressWarnings("all")
@lombok.Generated
public JacksonizedAccessorsJackson3() {
}
@com.fasterxml.jackson.annotation.JsonProperty("name")
@java.lang.SuppressWarnings("all")
@lombok.Generated
public String name() {
return this.name;
}
@com.fasterxml.jackson.annotation.JsonProperty("age")
@java.lang.SuppressWarnings("all")
@lombok.Generated
public int age() {
return this.age;
}
@com.fasterxml.jackson.annotation.JsonIgnore
@java.lang.SuppressWarnings("all")
@lombok.Generated
public String password() {
return this.password;
}
/**
* @return {@code this}.
*/
@com.fasterxml.jackson.annotation.JsonProperty("name")
@java.lang.SuppressWarnings("all")
@lombok.Generated
public JacksonizedAccessorsJackson3 name(final String name) {
this.name = name;
return this;
}
/**
* @return {@code this}.
*/
@com.fasterxml.jackson.annotation.JsonProperty("age")
@java.lang.SuppressWarnings("all")
@lombok.Generated
public JacksonizedAccessorsJackson3 age(final int age) {
this.age = age;
return this;
}
/**
* @return {@code this}.
*/
@com.fasterxml.jackson.annotation.JsonIgnore
@java.lang.SuppressWarnings("all")
@lombok.Generated
public JacksonizedAccessorsJackson3 password(final String password) {
this.password = password;
return this;
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
@lombok.Generated
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof JacksonizedAccessorsJackson3)) return false;
final JacksonizedAccessorsJackson3 other = (JacksonizedAccessorsJackson3) o;
if (!other.canEqual((java.lang.Object) this)) return false;
if (this.age() != other.age()) return false;
final java.lang.Object this$name = this.name();
final java.lang.Object other$name = other.name();
if (this$name == null ? other$name != null : !this$name.equals(other$name)) return false;
return true;
}
@java.lang.SuppressWarnings("all")
@lombok.Generated
protected boolean canEqual(final java.lang.Object other) {
return other instanceof JacksonizedAccessorsJackson3;
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
@lombok.Generated
public int hashCode() {
final int PRIME = 59;
int result = 1;
result = result * PRIME + this.age();
final java.lang.Object $name = this.name();
result = result * PRIME + ($name == null ? 43 : $name.hashCode());
return result;
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
@lombok.Generated
public java.lang.String toString() {
return "JacksonizedAccessorsJackson3(name=" + this.name() + ", age=" + this.age() + ", password=" + this.password() + ")";
}
}
@@ -0,0 +1,68 @@
@lombok.Data @lombok.experimental.Accessors(fluent = true) @lombok.extern.jackson.Jacksonized class JacksonizedAccessorsJackson3 {
private @com.fasterxml.jackson.annotation.JsonProperty("name") String name;
private @com.fasterxml.jackson.annotation.JsonProperty("age") int age;
private transient @com.fasterxml.jackson.annotation.JsonIgnore String password;
public @com.fasterxml.jackson.annotation.JsonProperty("name") @java.lang.SuppressWarnings("all") @lombok.Generated String name() {
return this.name;
}
public @com.fasterxml.jackson.annotation.JsonProperty("age") @java.lang.SuppressWarnings("all") @lombok.Generated int age() {
return this.age;
}
public @com.fasterxml.jackson.annotation.JsonIgnore @java.lang.SuppressWarnings("all") @lombok.Generated String password() {
return this.password;
}
/**
* @return {@code this}.
*/
public @com.fasterxml.jackson.annotation.JsonProperty("name") @java.lang.SuppressWarnings("all") @lombok.Generated JacksonizedAccessorsJackson3 name(final String name) {
this.name = name;
return this;
}
/**
* @return {@code this}.
*/
public @com.fasterxml.jackson.annotation.JsonProperty("age") @java.lang.SuppressWarnings("all") @lombok.Generated JacksonizedAccessorsJackson3 age(final int age) {
this.age = age;
return this;
}
/**
* @return {@code this}.
*/
public @com.fasterxml.jackson.annotation.JsonIgnore @java.lang.SuppressWarnings("all") @lombok.Generated JacksonizedAccessorsJackson3 password(final String password) {
this.password = password;
return this;
}
public @java.lang.Override @java.lang.SuppressWarnings("all") @lombok.Generated boolean equals(final java.lang.Object o) {
if ((o == this))
return true;
if ((! (o instanceof JacksonizedAccessorsJackson3)))
return false;
final JacksonizedAccessorsJackson3 other = (JacksonizedAccessorsJackson3) o;
if ((! other.canEqual((java.lang.Object) this)))
return false;
if ((this.age() != other.age()))
return false;
final java.lang.Object this$name = this.name();
final java.lang.Object other$name = other.name();
if (((this$name == null) ? (other$name != null) : (! this$name.equals(other$name))))
return false;
return true;
}
protected @java.lang.SuppressWarnings("all") @lombok.Generated boolean canEqual(final java.lang.Object other) {
return (other instanceof JacksonizedAccessorsJackson3);
}
public @java.lang.Override @java.lang.SuppressWarnings("all") @lombok.Generated int hashCode() {
final int PRIME = 59;
int result = 1;
result = ((result * PRIME) + this.age());
final java.lang.Object $name = this.name();
result = ((result * PRIME) + (($name == null) ? 43 : $name.hashCode()));
return result;
}
public @java.lang.Override @java.lang.SuppressWarnings("all") @lombok.Generated java.lang.String toString() {
return (((((("JacksonizedAccessorsJackson3(name=" + this.name()) + ", age=") + this.age()) + ", password=") + this.password()) + ")");
}
public @java.lang.SuppressWarnings("all") @lombok.Generated JacksonizedAccessorsJackson3() {
super();
}
}
@@ -0,0 +1,10 @@
//version 8: Jackson deps are at least Java7+.
//CONF: lombok.jacksonized.jacksonVersion += 3
@lombok.Data
@lombok.experimental.Accessors(fluent = true)
@lombok.extern.jackson.Jacksonized
class JacksonizedAccessorsJackson3 {
private String name;
private int age;
private transient String password;
}
@@ -0,0 +1 @@
1 Ambiguous: Jackson2 and Jackson3 exist; define which variant(s) you want in 'lombok.config'. See https://projectlombok.org/features/experimental/Jacksonized
@@ -0,0 +1 @@
1 Ambiguous: Jackson2 and Jackson3 exist; define which variant(s) you want in 'lombok.config'. See https://projectlombok.org/features/experimental/Jacksonized
@@ -0,0 +1 @@
1 Ambiguous: Jackson2 and Jackson3 exist; define which variant(s) you want in 'lombok.config'. See https://projectlombok.org/features/experimental/Jacksonized
@@ -0,0 +1 @@
1 Ambiguous: Jackson2 and Jackson3 exist; define which variant(s) you want in 'lombok.config'. See https://projectlombok.org/features/experimental/Jacksonized
@@ -1 +1,2 @@
2 Ambiguous: Jackson2 and Jackson3 exist; define which variant(s) you want in 'lombok.config'. See https://projectlombok.org/features/experimental/Jacksonized
2 @JsonDeserialize already exists on class. Either delete @JsonDeserialize, or remove @Jacksonized and manually configure Jackson.