Skip to content

Commit

Permalink
Merge pull request #1136 from altro3/json_view_fields
Browse files Browse the repository at this point in the history
Add ability to change JsonView default inclusion
  • Loading branch information
altro3 authored Jul 19, 2023
2 parents 1fda776 + 202d616 commit 73077de
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@
import static io.micronaut.openapi.visitor.OpenApiApplicationVisitor.expandProperties;
import static io.micronaut.openapi.visitor.OpenApiApplicationVisitor.getConfigurationProperty;
import static io.micronaut.openapi.visitor.OpenApiApplicationVisitor.getExpandableProperties;
import static io.micronaut.openapi.visitor.OpenApiApplicationVisitor.isJsonViewDefaultInclusion;
import static io.micronaut.openapi.visitor.OpenApiApplicationVisitor.resolvePlaceholders;
import static io.micronaut.openapi.visitor.SchemaUtils.TYPE_OBJECT;
import static io.micronaut.openapi.visitor.SchemaUtils.processExtensions;
Expand Down Expand Up @@ -2433,7 +2434,7 @@ private void processPropertyElements(OpenAPI openAPI, VisitorContext context, El
continue;
}

if (withJsonView && notAllowedByJsonView(publicField, classLvlJsonViewClasses, jsonViewClass, context)) {
if (withJsonView && !allowedByJsonView(publicField, classLvlJsonViewClasses, jsonViewClass, context)) {
continue;
}

Expand All @@ -2457,7 +2458,7 @@ private void processPropertyElements(OpenAPI openAPI, VisitorContext context, El
}
}

if (withJsonView && notAllowedByJsonView(publicField, classLvlJsonViewClasses, jsonViewClass, context)) {
if (withJsonView && !allowedByJsonView(publicField, classLvlJsonViewClasses, jsonViewClass, context)) {
continue;
}

Expand All @@ -2475,22 +2476,22 @@ private void processPropertyElements(OpenAPI openAPI, VisitorContext context, El
}
}

private boolean notAllowedByJsonView(TypedElement publicField, String[] classLvlJsonViewClasses, ClassElement jsonViewClassEl, VisitorContext context) {
private boolean allowedByJsonView(TypedElement publicField, String[] classLvlJsonViewClasses, ClassElement jsonViewClassEl, VisitorContext context) {
String[] fieldJsonViewClasses = publicField.getAnnotationMetadata().stringValues(JsonView.class);
if (ArrayUtils.isEmpty(fieldJsonViewClasses)) {
fieldJsonViewClasses = classLvlJsonViewClasses;
}
if (ArrayUtils.isEmpty(fieldJsonViewClasses)) {
return false;
return isJsonViewDefaultInclusion(context);
}

for (String fieldJsonViewClass : fieldJsonViewClasses) {
if (jsonViewClassEl.isAssignable(context.getClassElement(fieldJsonViewClass).get())) {
return false;
return true;
}
}

return true;
return false;
}

private Schema getPrimitiveType(String typeName) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@
OpenApiApplicationVisitor.MICRONAUT_OPENAPI_CONFIG_FILE,
OpenApiApplicationVisitor.MICRONAUT_OPENAPI_SECURITY_ENABLED,
OpenApiApplicationVisitor.MICRONAUT_OPENAPI_VERSIONING_ENABLED,
OpenApiApplicationVisitor.MICRONAUT_OPENAPI_JSON_VIEW_DEFAULT_INCLUSION,
})
public class OpenApiApplicationVisitor extends AbstractOpenApiVisitor implements TypeElementVisitor<OpenAPIDefinition, Object> {

Expand Down Expand Up @@ -251,6 +252,13 @@ public class OpenApiApplicationVisitor extends AbstractOpenApiVisitor implements
* directory.
*/
public static final String MICRONAUT_CONFIG_FILE_LOCATIONS = "micronaut.openapi.config.file.locations";
/**
* Property that determines whether properties that have no view annotations are included in JSON serialization views.
* If enabled, non-annotated properties will be included; when disabled, they will be excluded.
* <br>
* Default value is "true".
*/
public static final String MICRONAUT_OPENAPI_JSON_VIEW_DEFAULT_INCLUSION = "micronaut.openapi.json.view.default.inclusion";

/**
* Loaded micronaut-http server context path property.
Expand All @@ -272,6 +280,10 @@ public class OpenApiApplicationVisitor extends AbstractOpenApiVisitor implements
* Loaded into context jackson.json-view.enabled property value.
*/
private static final String MICRONAUT_INTERNAL_JACKSON_JSON_VIEW_ENABLED = "micronaut.internal.jackson.json-view.enabled";
/**
* Loaded into context micronaut.openapi.json-view.default-inclusion property value.
*/
private static final String MICRONAUT_INTERNAL_JACKSON_JSON_VIEW_DEFAULT_INCLUSION = "micronaut.internal.json-view.default-inclusion";
private static final String MICRONAUT_ENVIRONMENT_CREATED = "micronaut.environment.created";
private static final String MICRONAUT_OPENAPI_PROPERTIES = "micronaut.openapi.properties";
private static final String MICRONAUT_OPENAPI_ENDPOINTS = "micronaut.openapi.endpoints";
Expand Down Expand Up @@ -639,6 +651,19 @@ public static boolean isJsonViewEnabled(VisitorContext context) {
return isJsonViewEnabled;
}

public static boolean isJsonViewDefaultInclusion(VisitorContext context) {

Boolean isJsonViewDefaultInclusion = context.get(MICRONAUT_INTERNAL_JACKSON_JSON_VIEW_DEFAULT_INCLUSION, Boolean.class).orElse(null);
if (isJsonViewDefaultInclusion != null) {
return isJsonViewDefaultInclusion;
}

isJsonViewDefaultInclusion = getBooleanProperty(MICRONAUT_OPENAPI_JSON_VIEW_DEFAULT_INCLUSION, true, context);
context.put(MICRONAUT_INTERNAL_JACKSON_JSON_VIEW_DEFAULT_INCLUSION, isJsonViewDefaultInclusion);

return isJsonViewDefaultInclusion;
}

public static SecurityProperties getSecurityProperties(VisitorContext context) {

SecurityProperties securityProperties = context.get(MICRONAUT_INTERNAL_SECURITY_PROPERTIES, SecurityProperties.class).orElse(null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -227,4 +227,88 @@ class MyBean {}
cleanup:
System.clearProperty(OpenApiApplicationVisitor.MICRONAUT_JACKSON_JSON_VIEW_ENABLED)
}

void "test build OpenAPI with changed JsonView default inclusion"() {

setup:
System.setProperty(OpenApiApplicationVisitor.MICRONAUT_JACKSON_JSON_VIEW_ENABLED, "true")
System.setProperty(OpenApiApplicationVisitor.MICRONAUT_OPENAPI_JSON_VIEW_DEFAULT_INCLUSION, "false")

when:
buildBeanDefinition('test.MyBean', '''
package test;
import java.util.List;
import io.micronaut.http.HttpResponse;
import io.micronaut.http.annotation.Body;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
import io.micronaut.http.annotation.Post;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import com.fasterxml.jackson.annotation.JsonView;
@Controller
class OpenApiController {
@Get("/summary")
@JsonView(View.Summary.class)
@Operation(summary = "Return car summaries",
responses = @ApiResponse(responseCode = "200", content = @Content(array = @ArraySchema(schema = @Schema(implementation = Car.class)))))
public HttpResponse<?> getSummaries() {
return null;
}
}
interface View {
interface Summary {}
}
class Car {
@JsonView(View.Summary.class)
public String made;
public String model;
public List<Tire> tires;
public int price;
public int age;
public String color;
}
class Tire {
public String made;
public String condition;
}
@jakarta.inject.Singleton
class MyBean {}
''')
then: "the state is correct"
Utils.testReference != null

when: "The OpenAPI is retrieved"
OpenAPI openAPI = Utils.testReference
Schema carSummary = openAPI.components.schemas['Car_Summary']
Operation summaryOp = openAPI.paths."/summary".get

then:

summaryOp
summaryOp.responses.'200'.content.'application/json'.schema.items.$ref == '#/components/schemas/Car_Summary'

carSummary
carSummary.properties.size() == 1
carSummary.properties.made

cleanup:
System.clearProperty(OpenApiApplicationVisitor.MICRONAUT_JACKSON_JSON_VIEW_ENABLED)
System.clearProperty(OpenApiApplicationVisitor.MICRONAUT_OPENAPI_JSON_VIEW_DEFAULT_INCLUSION)
}
}

0 comments on commit 73077de

Please sign in to comment.