Skip to content

Commit d3d1131

Browse files
authored
Merge pull request #46929 from mariofusco/jsoncreator
Add support for JsonCreator and fluent setters in reflection-free Jackson serialization
2 parents c843e47 + 164835d commit d3d1131

File tree

7 files changed

+127
-11
lines changed

7 files changed

+127
-11
lines changed

extensions/resteasy-reactive/rest-jackson/deployment/src/main/java/io/quarkus/resteasy/reactive/jackson/deployment/processor/JacksonCodeGenerator.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.jboss.jandex.Type;
2626
import org.jboss.jandex.TypeVariable;
2727

28+
import com.fasterxml.jackson.annotation.JsonCreator;
2829
import com.fasterxml.jackson.annotation.JsonIgnore;
2930
import com.fasterxml.jackson.annotation.JsonProperty;
3031

@@ -344,7 +345,9 @@ boolean isIgnoredField() {
344345

345346
private static boolean isUnknownAnnotation(String ann) {
346347
if (ann.startsWith("com.fasterxml.jackson.")) {
347-
return !ann.equals(JsonProperty.class.getName()) && !ann.equals(JsonIgnore.class.getName());
348+
return !ann.equals(JsonProperty.class.getName()) &&
349+
!ann.equals(JsonIgnore.class.getName()) &&
350+
!ann.equals(JsonCreator.class.getName());
348351
}
349352
return false;
350353
}

extensions/resteasy-reactive/rest-jackson/deployment/src/main/java/io/quarkus/resteasy/reactive/jackson/deployment/processor/JacksonDeserializerFactory.java

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import org.jboss.jandex.*;
1919

20+
import com.fasterxml.jackson.annotation.JsonCreator;
2021
import com.fasterxml.jackson.core.JacksonException;
2122
import com.fasterxml.jackson.core.JsonParser;
2223
import com.fasterxml.jackson.core.ObjectCodec;
@@ -231,15 +232,22 @@ private static ResultHandle getJsonNode(MethodCreator deserialize) {
231232
}
232233

233234
private ResultHandle createDeserializedObject(DeserializationData deserData) {
234-
if (deserData.classInfo.hasNoArgsConstructor() && !deserData.classInfo.isRecord()) {
235-
return deserData.methodCreator.newInstance(MethodDescriptor.ofConstructor(deserData.classInfo.name().toString()));
235+
var ctorOpt = deserData.classInfo.constructors().stream()
236+
.filter(ctor -> Modifier.isPublic(ctor.flags()) && ctor.hasAnnotation(JsonCreator.class))
237+
.findFirst();
238+
239+
if (ctorOpt.isEmpty()) {
240+
if (deserData.classInfo.hasNoArgsConstructor() && !deserData.classInfo.isRecord()) {
241+
return deserData.methodCreator
242+
.newInstance(MethodDescriptor.ofConstructor(deserData.classInfo.name().toString()));
243+
}
244+
ctorOpt = deserData.classInfo.isRecord() ? Optional.of(deserData.classInfo.canonicalRecordConstructor())
245+
: deserData.classInfo.constructors().stream().filter(ctor -> Modifier.isPublic(ctor.flags())).findFirst();
246+
if (ctorOpt.isEmpty()) {
247+
return null;
248+
}
236249
}
237250

238-
var ctorOpt = deserData.classInfo.isRecord() ? Optional.of(deserData.classInfo.canonicalRecordConstructor())
239-
: deserData.classInfo.constructors().stream().filter(ctor -> Modifier.isPublic(ctor.flags())).findFirst();
240-
if (!ctorOpt.isPresent()) {
241-
return null;
242-
}
243251
MethodInfo ctor = ctorOpt.get();
244252
ResultHandle[] params = new ResultHandle[ctor.parameters().size()];
245253
int i = 0;
@@ -452,7 +460,11 @@ private void writeValueToObject(ClassInfo classInfo, ResultHandle objHandle, Fie
452460

453461
private MethodInfo setterMethodInfo(ClassInfo classInfo, FieldSpecs fieldSpecs) {
454462
String methodName = "set" + ucFirst(fieldSpecs.fieldName);
455-
return findMethod(classInfo, methodName, fieldSpecs.fieldType);
463+
MethodInfo setter = findMethod(classInfo, methodName, fieldSpecs.fieldType);
464+
if (setter == null) {
465+
setter = findMethod(classInfo, fieldSpecs.fieldName, fieldSpecs.fieldType);
466+
}
467+
return setter;
456468
}
457469

458470
private MethodDescriptor readMethodForPrimitiveFields(String typeName) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package io.quarkus.resteasy.reactive.jackson.deployment.test;
2+
3+
import com.fasterxml.jackson.annotation.JsonCreator;
4+
5+
public class Book {
6+
7+
private String title;
8+
private String author;
9+
10+
public Book() {
11+
}
12+
13+
@JsonCreator
14+
public Book(String title, String author) {
15+
this.title = title;
16+
this.author = author;
17+
}
18+
19+
public Book(String title) {
20+
this(title, null);
21+
}
22+
23+
public String getTitle() {
24+
return title;
25+
}
26+
27+
public void setTitle(String title) {
28+
this.title = title;
29+
}
30+
31+
public String getAuthor() {
32+
return author;
33+
}
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package io.quarkus.resteasy.reactive.jackson.deployment.test;
2+
3+
public class LombokBook {
4+
5+
private String title;
6+
private String author;
7+
8+
public String getTitle() {
9+
return title;
10+
}
11+
12+
public LombokBook title(String title) {
13+
this.title = title;
14+
return this;
15+
}
16+
17+
public String getAuthor() {
18+
return author;
19+
}
20+
21+
public LombokBook author(String author) {
22+
this.author = author;
23+
return this;
24+
}
25+
}

extensions/resteasy-reactive/rest-jackson/deployment/src/test/java/io/quarkus/resteasy/reactive/jackson/deployment/test/SimpleJsonResource.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,20 @@ public Dog echoDog(Dog dog) {
109109
return dog;
110110
}
111111

112+
@POST
113+
@Path("/book-echo")
114+
@Consumes(MediaType.APPLICATION_JSON)
115+
public Book echoBook(Book book) {
116+
return book;
117+
}
118+
119+
@POST
120+
@Path("/lombok-book-echo")
121+
@Consumes(MediaType.APPLICATION_JSON)
122+
public LombokBook echoLombokBook(LombokBook book) {
123+
return book;
124+
}
125+
112126
@POST
113127
@Path("/record-echo")
114128
@Consumes(MediaType.APPLICATION_JSON)

extensions/resteasy-reactive/rest-jackson/deployment/src/test/java/io/quarkus/resteasy/reactive/jackson/deployment/test/SimpleJsonTest.java

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public JavaArchive get() {
3838
AbstractUnsecuredPet.class, UnsecuredPet.class, SecuredPersonInterface.class, Frog.class,
3939
Pond.class, FrogBodyParts.class, FrogBodyParts.BodyPart.class, ContainerDTO.class,
4040
NestedInterface.class, StateRecord.class, MapWrapper.class, GenericWrapper.class,
41-
Fruit.class, Price.class, DogRecord.class, ItemExtended.class)
41+
Fruit.class, Price.class, DogRecord.class, ItemExtended.class, Book.class, LombokBook.class)
4242
.addAsResource(new StringAsset("admin-expression=admin\n" +
4343
"user-expression=user\n" +
4444
"birth-date-roles=alice,bob\n"), "application.properties");
@@ -807,4 +807,32 @@ public void testItemExtended() {
807807
.body("nameExtended", Matchers.is("Name-Extended"))
808808
.body("emailExtended", Matchers.is(emptyOrNullString()));
809809
}
810+
811+
@Test
812+
public void testPojoWithJsonCreator() {
813+
RestAssured
814+
.with()
815+
.body("{\"author\":\"Stephen King\",\"title\":\"IT\"}")
816+
.contentType("application/json; charset=utf-8")
817+
.post("/simple/book-echo")
818+
.then()
819+
.statusCode(200)
820+
.contentType("application/json")
821+
.body("author", Matchers.is("Stephen King"))
822+
.body("title", Matchers.is("IT"));
823+
}
824+
825+
@Test
826+
public void testPojoWithFluentSetters() {
827+
RestAssured
828+
.with()
829+
.body("{\"author\":\"Mario Fusco\",\"title\":\"Lombok must die\"}")
830+
.contentType("application/json; charset=utf-8")
831+
.post("/simple/lombok-book-echo")
832+
.then()
833+
.statusCode(200)
834+
.contentType("application/json")
835+
.body("author", Matchers.is("Mario Fusco"))
836+
.body("title", Matchers.is("Lombok must die"));
837+
}
810838
}

extensions/resteasy-reactive/rest-jackson/deployment/src/test/java/io/quarkus/resteasy/reactive/jackson/deployment/test/SimpleJsonWithReflectionFreeSerializersTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public JavaArchive get() {
2828
AbstractUnsecuredPet.class, UnsecuredPet.class, SecuredPersonInterface.class, Frog.class,
2929
Pond.class, FrogBodyParts.class, FrogBodyParts.BodyPart.class, ContainerDTO.class,
3030
NestedInterface.class, StateRecord.class, MapWrapper.class, GenericWrapper.class,
31-
Fruit.class, Price.class, DogRecord.class, ItemExtended.class)
31+
Fruit.class, Price.class, DogRecord.class, ItemExtended.class, Book.class, LombokBook.class)
3232
.addAsResource(new StringAsset("admin-expression=admin\n" +
3333
"user-expression=user\n" +
3434
"birth-date-roles=alice,bob\n" +

0 commit comments

Comments
 (0)