Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support @JsonView on request body #43849

Merged
merged 1 commit into from
Oct 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,11 @@
import io.quarkus.resteasy.reactive.jackson.runtime.mappers.NativeInvalidDefinitionExceptionMapper;
import io.quarkus.resteasy.reactive.jackson.runtime.security.RolesAllowedConfigExpStorage;
import io.quarkus.resteasy.reactive.jackson.runtime.security.SecurityCustomSerialization;
import io.quarkus.resteasy.reactive.jackson.runtime.serialisers.*;
import io.quarkus.resteasy.reactive.jackson.runtime.serialisers.BasicServerJacksonMessageBodyWriter;
import io.quarkus.resteasy.reactive.jackson.runtime.serialisers.FullyFeaturedServerJacksonMessageBodyReader;
import io.quarkus.resteasy.reactive.jackson.runtime.serialisers.FullyFeaturedServerJacksonMessageBodyWriter;
import io.quarkus.resteasy.reactive.jackson.runtime.serialisers.GeneratedSerializersRegister;
import io.quarkus.resteasy.reactive.jackson.runtime.serialisers.ServerJacksonMessageBodyReader;
import io.quarkus.resteasy.reactive.jackson.runtime.serialisers.vertx.VertxJsonArrayMessageBodyReader;
import io.quarkus.resteasy.reactive.jackson.runtime.serialisers.vertx.VertxJsonArrayMessageBodyWriter;
import io.quarkus.resteasy.reactive.jackson.runtime.serialisers.vertx.VertxJsonObjectMessageBodyReader;
Expand Down Expand Up @@ -263,7 +267,7 @@ void handleJsonAnnotations(Optional<ResourceScanningResultBuildItem> resourceSca
if ((jsonViews == null) || (jsonViews.length == 0)) {
continue;
}
recorder.recordJsonView(getTargetId(instance.target()), jsonViews[0].name().toString());
recorder.recordJsonView(getTargetId(instance), jsonViews[0].name().toString());
}
}
if (resourceClass.annotationsMap().containsKey(CUSTOM_SERIALIZATION)) {
Expand All @@ -290,7 +294,7 @@ void handleJsonAnnotations(Optional<ResourceScanningResultBuildItem> resourceSca
ReflectiveClassBuildItem.builder(biFunctionType.name().toString())
.reason(getClass().getName())
.build());
recorder.recordCustomSerialization(getTargetId(instance.target()), biFunctionType.name().toString());
recorder.recordCustomSerialization(getTargetId(instance), biFunctionType.name().toString());
}
}
if (resourceClass.annotationsMap().containsKey(CUSTOM_DESERIALIZATION)) {
Expand All @@ -317,7 +321,7 @@ void handleJsonAnnotations(Optional<ResourceScanningResultBuildItem> resourceSca
ReflectiveClassBuildItem.builder(biFunctionType.name().toString())
.reason(getClass().getName())
.build());
recorder.recordCustomDeserialization(getTargetId(instance.target()), biFunctionType.name().toString());
recorder.recordCustomDeserialization(getTargetId(instance), biFunctionType.name().toString());
}
}
}
Expand Down Expand Up @@ -641,15 +645,18 @@ private static boolean fieldTypeHasSecureFields(Type fieldType, IndexView indexV
return false;
}

private String getTargetId(AnnotationTarget target) {
private String getTargetId(AnnotationInstance instance) {
AnnotationTarget target = instance.target();
if (target.kind() == AnnotationTarget.Kind.CLASS) {
return getClassId(target.asClass());
} else if (target.kind() == AnnotationTarget.Kind.METHOD) {
return getMethodId(target.asMethod());
} else if (target.kind() == AnnotationTarget.Kind.METHOD_PARAMETER) {
return getMethodId(target.asMethodParameter().method());
}

throw new UnsupportedOperationException("The `@CustomSerialization` and `@CustomDeserialization` annotations can only "
+ "be used in methods or classes.");
throw new UnsupportedOperationException(String.format("The `%s` annotation can only "
+ "be used in methods or classes.", instance.name()));
}

private String getClassId(ClassInfo classInfo) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package io.quarkus.resteasy.reactive.jackson.deployment.test;

import static io.restassured.RestAssured.given;
import static jakarta.ws.rs.core.Response.Status.CREATED;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.not;

import java.util.function.Supplier;

import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;

import org.jboss.resteasy.reactive.RestResponse;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import com.fasterxml.jackson.annotation.JsonView;

import io.quarkus.test.QuarkusUnitTest;

public class JsonViewOnMethodParameterTest {

@RegisterExtension
static QuarkusUnitTest test = new QuarkusUnitTest()
.setArchiveProducer(new Supplier<>() {
@Override
public JavaArchive get() {
return ShrinkWrap.create(JavaArchive.class)
.addClasses(User.class, Views.class, Resource.class);
}
});

@Test
public void test() {
given().accept("application/json")
.contentType("application/json")
.body("""
{
"id": 1,
"name": "Foo"
}
""")
.post("test")
.then()
.statusCode(201)
.body(not(containsString("1")), containsString("Foo"));
}

@Path("test")
public static class Resource {

@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public RestResponse<User> create(@JsonView(Views.Public.class) User user) {
return RestResponse.status(CREATED, user);
}
}
}
Loading