Skip to content

Commit

Permalink
Merge pull request #42914 from mariofusco/q42774
Browse files Browse the repository at this point in the history
Fix Jackson serializers generation for interfaces and boxed primitive types
  • Loading branch information
geoand authored Aug 30, 2024
2 parents fdefb00 + 7c81d83 commit 708a762
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ private void writeField(ClassInfo classInfo, FieldSpecs fieldSpecs, BytecodeCrea

if (primitiveMethodName != null) {
MethodDescriptor primitiveWriter = MethodDescriptor.ofMethod(JSON_GEN_CLASS_NAME, primitiveMethodName, "void",
typeName);
fieldSpecs.writtenType());
bytecode.invokeVirtualMethod(primitiveWriter, jsonGenerator, arg);
return;
}
Expand Down Expand Up @@ -372,7 +372,7 @@ private void registerTypeToBeGenerated(String typeName) {

private String writeMethodForPrimitiveFields(String typeName) {
return switch (typeName) {
case "java.lang.String" -> "writeString";
case "java.lang.String", "char", "java.lang.Character" -> "writeString";
case "short", "java.lang.Short", "int", "java.lang.Integer", "long", "java.lang.Long", "float",
"java.lang.Float", "double", "java.lang.Double" ->
"writeNumber";
Expand Down Expand Up @@ -590,8 +590,37 @@ boolean hasUnknownAnnotation() {
}

ResultHandle toValueReaderHandle(BytecodeCreator bytecode, ResultHandle valueHandle) {
return methodInfo != null ? bytecode.invokeVirtualMethod(MethodDescriptor.of(methodInfo), valueHandle)
: bytecode.readInstanceField(FieldDescriptor.of(fieldInfo), valueHandle);
ResultHandle handle = accessorHandle(bytecode, valueHandle);

handle = switch (fieldType.name().toString()) {
case "char", "java.lang.Character" -> bytecode.invokeStaticMethod(
MethodDescriptor.ofMethod(Character.class, "toString", String.class, char.class), handle);
default -> handle;
};

return handle;
}

private ResultHandle accessorHandle(BytecodeCreator bytecode, ResultHandle valueHandle) {
if (methodInfo != null) {
if (methodInfo.declaringClass().isInterface()) {
return bytecode.invokeInterfaceMethod(MethodDescriptor.of(methodInfo), valueHandle);
}
return bytecode.invokeVirtualMethod(MethodDescriptor.of(methodInfo), valueHandle);
}
return bytecode.readInstanceField(FieldDescriptor.of(fieldInfo), valueHandle);
}

String writtenType() {
return switch (fieldType.name().toString()) {
case "char", "java.lang.Character" -> "java.lang.String";
case "java.lang.Integer" -> "int";
case "java.lang.Short" -> "short";
case "java.lang.Long" -> "long";
case "java.lang.Double" -> "double";
case "java.lang.Float" -> "float";
default -> fieldType.name().toString();
};
}

private String[] rolesAllowed() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,8 @@ public int getPrivateAge() {
public void setPrivateAge(int privateAge) {
this.privateAge = privateAge;
}

public char getInitial() {
return getPublicName().charAt(0);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package io.quarkus.resteasy.reactive.jackson.deployment.test;

public record ContainerDTO(NestedInterface nestedInterface) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package io.quarkus.resteasy.reactive.jackson.deployment.test;

public interface NestedInterface {

NestedInterface INSTANCE = new NestedInterface() {
@Override
public String getString() {
return "response";
}

@Override
public Integer getInt() {
return 42;
}

@Override
public char getCharacter() {
return 'a';
}
};

String getString();

Integer getInt();

char getCharacter();

}
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,12 @@ public String genericInputTest(DataItem<Item> item) {
return item.getContent().getName();
}

@GET
@Path("/interface")
public ContainerDTO interfaceTest() {
return new ContainerDTO(NestedInterface.INSTANCE);
}

public static class UnquotedFieldsPersonSerialization implements BiFunction<ObjectMapper, Type, ObjectWriter> {

public static final AtomicInteger count = new AtomicInteger();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ public JavaArchive get() {
NoopReaderInterceptor.class, TestIdentityProvider.class, TestIdentityController.class,
AbstractPet.class, Dog.class, Cat.class, Veterinarian.class, AbstractNamedPet.class,
AbstractUnsecuredPet.class, UnsecuredPet.class, SecuredPersonInterface.class, Frog.class,
Pond.class, FrogBodyParts.class, FrogBodyParts.BodyPart.class)
Pond.class, FrogBodyParts.class, FrogBodyParts.BodyPart.class, ContainerDTO.class,
NestedInterface.class)
.addAsResource(new StringAsset("admin-expression=admin\n" +
"user-expression=user\n" +
"birth-date-roles=alice,bob\n"), "application.properties");
Expand Down Expand Up @@ -506,6 +507,18 @@ public void testGenericInput() {
.body(is("foo"));
}

@Test
public void testInterface() {
RestAssured
.with()
.get("/simple/interface")
.then()
.statusCode(200)
.body("nestedInterface.int", Matchers.is(42))
.body("nestedInterface.character", Matchers.is("a"))
.body("nestedInterface.string", Matchers.is("response"));
}

@Test
public void testSecureFieldOnAbstractClass() {
// implementor with / without @SecureField returned
Expand Down Expand Up @@ -602,6 +615,7 @@ private static void testSecuredFieldOnAbstractClass(String catPath, String dogPa
.then()
.statusCode(200)
.body("publicName", Matchers.is("Garfield"))
.body("initial", Matchers.is("G"))
.body("privateName", Matchers.nullValue())
.body("veterinarian.name", Matchers.is("Dolittle"))
.body("veterinarian.title", Matchers.nullValue())
Expand All @@ -625,6 +639,7 @@ private static void testSecuredFieldOnAbstractClass(String catPath, String dogPa
.then()
.statusCode(200)
.body("publicName", Matchers.is("Garfield"))
.body("initial", Matchers.is("G"))
.body("privateName", Matchers.is("Monday"))
.body("privateAge", Matchers.is(4))
.body("veterinarian.name", Matchers.is("Dolittle"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ public JavaArchive get() {
NoopReaderInterceptor.class, TestIdentityProvider.class, TestIdentityController.class,
AbstractPet.class, Dog.class, Cat.class, Veterinarian.class, AbstractNamedPet.class,
AbstractUnsecuredPet.class, UnsecuredPet.class, SecuredPersonInterface.class, Frog.class,
Pond.class, FrogBodyParts.class, FrogBodyParts.BodyPart.class)
Pond.class, FrogBodyParts.class, FrogBodyParts.BodyPart.class, ContainerDTO.class,
NestedInterface.class)
.addAsResource(new StringAsset("admin-expression=admin\n" +
"user-expression=user\n" +
"birth-date-roles=alice,bob\n" +
Expand Down

0 comments on commit 708a762

Please sign in to comment.