11/*
2- * Copyright (C) 2020-2025 The Project Lombok Authors.
2+ * Copyright (C) 2020-2026 The Project Lombok Authors.
33 *
44 * Permission is hereby granted, free of charge, to any person obtaining a copy
55 * of this software and associated documentation files (the "Software"), to deal
4343import lombok .ConfigurationKeys ;
4444import lombok .core .AnnotationValues ;
4545import lombok .core .HandlerPriority ;
46+ import lombok .core .JacksonAnnotationType ;
4647import lombok .core .AST .Kind ;
4748import lombok .core .configuration .JacksonVersion ;
4849import lombok .core .handlers .HandlerUtil ;
6263@ Provides
6364@ HandlerPriority (-512 ) // Above Handle(Super)Builder's level (builders must be already generated).
6465public class HandleJacksonized extends EclipseAnnotationHandler <Jacksonized > {
65-
66- private static final char [][] JACKSON3_JSON_POJO_BUILDER_ANNOTATION = Eclipse .fromQualifiedName ("tools.jackson.databind.annotation.JsonPOJOBuilder" );
67- private static final char [][] JACKSON2_JSON_POJO_BUILDER_ANNOTATION = Eclipse .fromQualifiedName ("com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder" );
68- private static final char [][] JACKSON3_JSON_DESERIALIZE_ANNOTATION = Eclipse .fromQualifiedName ("tools.jackson.databind.annotation.JsonDeserialize" );
69- private static final char [][] JACKSON2_JSON_DESERIALIZE_ANNOTATION = Eclipse .fromQualifiedName ("com.fasterxml.jackson.databind.annotation.JsonDeserialize" );
70- private static final char [][] JSON_PROPERTY_ANNOTATION = Eclipse .fromQualifiedName ("com.fasterxml.jackson.annotation.JsonProperty" );
66+ static boolean hasAnnotation (EclipseNode node , JacksonAnnotationType annotation ) {
67+ return EclipseHandlerUtil .hasAnnotation (annotation .getQualifiedName (), node );
68+ }
7169
7270 @ Override public void handle (AnnotationValues <Jacksonized > annotation , Annotation ast , EclipseNode annotationNode ) {
7371 handleExperimentalFlagUsage (annotationNode , ConfigurationKeys .JACKSONIZED_FLAG_USAGE , "@Jacksonized" );
@@ -135,31 +133,30 @@ private void handleJacksonizedBuilder(Annotation ast, EclipseNode annotationNode
135133 }
136134
137135 // Insert @JsonDeserialize on annotated class.
138- if (hasAnnotation ("com.fasterxml.jackson.databind.annotation.JsonDeserialize" , tdNode )) {
139- annotationNode .addError ("@JsonDeserialize already exists on class. Either delete @JsonDeserialize, or remove @Jacksonized and manually configure Jackson." );
140- return ;
141- }
142- if (hasAnnotation ("tools.jackson.databind.annotation.JsonDeserialize" , tdNode )) {
136+ if (hasAnnotation (tdNode , JacksonAnnotationType .JSON_DESERIALIZE2 ) || hasAnnotation (tdNode , JacksonAnnotationType .JSON_DESERIALIZE3 )) {
143137 annotationNode .addError ("@JsonDeserialize already exists on class. Either delete @JsonDeserialize, or remove @Jacksonized and manually configure Jackson." );
144138 return ;
145139 }
146140 long p = (long ) ast .sourceStart << 32 | ast .sourceEnd ;
147141 TypeReference builderClassExpression = namePlusTypeParamsToTypeReference (builderClassNode , null , p );
148142 ClassLiteralAccess builderClassLiteralAccess = new ClassLiteralAccess (td .sourceEnd , builderClassExpression );
149143 MemberValuePair builderMvp = new MemberValuePair ("builder" .toCharArray (), td .sourceStart , td .sourceEnd , builderClassLiteralAccess );
150-
151- JacksonVersion jacksonVersion = annotationNode .getAst ().readConfigurationOr (ConfigurationKeys .JACKSONIZED_JACKSON_VERSION , JacksonVersion .getDefault ());
152- if (jacksonVersion == null || !jacksonVersion .isValid ()) {
153- annotationNode .addError ("No valid jackson version selected." );
154- return ;
144+
145+ List <JacksonVersion > jacksonVersions = annotationNode .getAst ().readConfigurationOr (ConfigurationKeys .JACKSONIZED_JACKSON_VERSION , Arrays .<JacksonVersion >asList ());
146+
147+ if (jacksonVersions .isEmpty ()) {
148+ annotationNode .addWarning ("Ambiguous: Jackson2 and Jackson3 exist; define which variant(s) you want in 'lombok.config'. See https://projectlombok.org/features/experimental/Jacksonized" );
149+ jacksonVersions = Arrays .asList (JacksonVersion .TWO );
155150 }
156-
157- if (jacksonVersion . useJackson2 ( )) {
158- td .annotations = addAnnotation (td , td .annotations , JACKSON2_JSON_DESERIALIZE_ANNOTATION , builderMvp );
151+
152+ if (jacksonVersions . contains ( JacksonVersion . TWO )) {
153+ td .annotations = addAnnotation (td , td .annotations , JacksonAnnotationType . JSON_DESERIALIZE2 . getQualifiednameAsCharArrayArray () , builderMvp );
159154 }
160- if (jacksonVersion .useJackson3 ()) {
161- td .annotations = addAnnotation (td , td .annotations , JACKSON3_JSON_DESERIALIZE_ANNOTATION , builderMvp );
155+
156+ if (jacksonVersions .contains (JacksonVersion .THREE )) {
157+ td .annotations = addAnnotation (td , td .annotations , JacksonAnnotationType .JSON_DESERIALIZE3 .getQualifiednameAsCharArrayArray (), builderMvp );
162158 }
159+
163160 // Copy annotations from the class to the builder class.
164161 Annotation [] copyableAnnotations = findJacksonAnnotationsOnClass (td , tdNode );
165162 builderClass .annotations = copyAnnotations (builderClass , builderClass .annotations , copyableAnnotations );
@@ -169,15 +166,16 @@ private void handleJacksonizedBuilder(Annotation ast, EclipseNode annotationNode
169166 MemberValuePair withPrefixMvp = new MemberValuePair ("withPrefix" .toCharArray (), builderClass .sourceStart , builderClass .sourceEnd , withPrefixLiteral );
170167 StringLiteral buildMethodNameLiteral = new StringLiteral (buildMethodName .toCharArray (), builderClass .sourceStart , builderClass .sourceEnd , 0 );
171168 MemberValuePair buildMethodNameMvp = new MemberValuePair ("buildMethodName" .toCharArray (), builderClass .sourceStart , builderClass .sourceEnd , buildMethodNameLiteral );
172- if (jacksonVersion .useJackson2 ()) {
173- builderClass .annotations = addAnnotation (builderClass , builderClass .annotations , JACKSON2_JSON_POJO_BUILDER_ANNOTATION , withPrefixMvp , buildMethodNameMvp );
169+
170+ if (jacksonVersions .contains (JacksonVersion .TWO )) {
171+ builderClass .annotations = addAnnotation (builderClass , builderClass .annotations , JacksonAnnotationType .JSON_POJO_BUILDER2 .getQualifiednameAsCharArrayArray (), withPrefixMvp , buildMethodNameMvp );
174172 }
175- if (jacksonVersion . useJackson3 ( )) {
176- builderClass .annotations = addAnnotation (builderClass , builderClass .annotations , JACKSON3_JSON_POJO_BUILDER_ANNOTATION , withPrefixMvp , buildMethodNameMvp );
173+ if (jacksonVersions . contains ( JacksonVersion . THREE )) {
174+ builderClass .annotations = addAnnotation (builderClass , builderClass .annotations , JacksonAnnotationType . JSON_POJO_BUILDER3 . getQualifiednameAsCharArrayArray () , withPrefixMvp , buildMethodNameMvp );
177175 }
176+
178177 // @SuperBuilder? Make it package-private!
179- if (superBuilderAnnotationNode != null )
180- builderClass .modifiers = builderClass .modifiers & ~ClassFileConstants .AccPrivate ;
178+ if (superBuilderAnnotationNode != null ) builderClass .modifiers = builderClass .modifiers & ~ClassFileConstants .AccPrivate ;
181179 }
182180
183181 private void handleJacksonizedAccessors (Annotation ast , EclipseNode annotationNode , EclipseNode annotatedNode , EclipseNode tdNode , TypeDeclaration td , EclipseNode accessorsAnnotationNode , boolean jacksonizedBuilder ) {
@@ -196,19 +194,33 @@ private void handleJacksonizedAccessors(Annotation ast, EclipseNode annotationNo
196194 // Add @JsonProperty to all fields. It will be automatically copied to the getter/setters later.
197195 for (EclipseNode eclipseNode : tdNode .down ()) {
198196 if (eclipseNode .getKind () == Kind .FIELD ) {
199- createJsonPropertyForField (eclipseNode , annotationNode );
197+ if (hasAnnotation (eclipseNode , JacksonAnnotationType .JSON_PROPERTY2 ) ||
198+ hasAnnotation (eclipseNode , JacksonAnnotationType .JSON_IGNORE2 )) {
199+ return ;
200+ } else if (eclipseNode .isTransient ()) {
201+ createJsonIgnoreForField (eclipseNode , annotationNode );
202+ } else {
203+ createJsonPropertyForField (eclipseNode , annotationNode );
204+ }
200205 }
201206 }
202207 tdNode .rebuild ();
203208 }
204209
205210 private void createJsonPropertyForField (EclipseNode fieldNode , EclipseNode annotationNode ) {
206- if (hasAnnotation ("com.fasterxml.jackson.annotation.JsonProperty" , fieldNode )) return ;
207211 ASTNode astNode = fieldNode .get ();
208212 if (astNode instanceof FieldDeclaration ) {
209- FieldDeclaration fd = (FieldDeclaration )astNode ;
213+ FieldDeclaration fd = (FieldDeclaration ) astNode ;
210214 StringLiteral fieldName = new StringLiteral (fd .name , 0 , 0 , 0 );
211- ((FieldDeclaration ) astNode ).annotations = addAnnotation (fieldNode .get (), fd .annotations , JSON_PROPERTY_ANNOTATION , fieldName );
215+ ((FieldDeclaration ) astNode ).annotations = addAnnotation (fieldNode .get (), fd .annotations , JacksonAnnotationType .JSON_PROPERTY2 .getQualifiednameAsCharArrayArray (), fieldName );
216+ }
217+ }
218+
219+ private void createJsonIgnoreForField (EclipseNode fieldNode , EclipseNode annotationNode ) {
220+ ASTNode astNode = fieldNode .get ();
221+ if (astNode instanceof FieldDeclaration ) {
222+ FieldDeclaration fd = (FieldDeclaration ) astNode ;
223+ ((FieldDeclaration ) astNode ).annotations = addAnnotation (fieldNode .get (), fd .annotations , JacksonAnnotationType .JSON_IGNORE2 .getQualifiednameAsCharArrayArray ());
212224 }
213225 }
214226
0 commit comments