Skip to content

Commit

Permalink
feat: swagger-2 additionalProperties support (#355)
Browse files Browse the repository at this point in the history
  • Loading branch information
CarstenWickner authored May 27, 2023
1 parent ea8b3f2 commit 246449e
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 4 deletions.
6 changes: 4 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### `jsonschema-module-swagger-2`
#### Added
- consider `@Schema(additionalProperties = ...)` attribute (only values `TRUE` and `FALSE`), when it is annotated on a type (not on a member)

## [4.31.1] - 2023-04-28
### `jsonschema-generator`
Expand Down Expand Up @@ -83,7 +85,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- enable look-up of annotations on a member's type parameter (e.g., a `Map`'s value type)
- enable providing full custom schema definition to be included in `additionalProperties` or `patternProperties`
- new function `TypeContext.getTypeWithAnnotation()` for finding also super type of interface with certain type annotation
- new function `TypeContext.getTypeAnnotationConsideringHierarchy()´ for searching type annotations also on super types and interfaces
- new function `TypeContext.getTypeAnnotationConsideringHierarchy()` for searching type annotations also on super types and interfaces

#### Changed
- consider annotations on `Map` value types when using `Option.MAP_VALUES_AS_ADDITIONAL_PROPERTIES`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,13 @@
import com.github.victools.jsonschema.generator.TypeScope;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Schema;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
Expand All @@ -60,6 +62,7 @@ public void applyToConfigBuilder(SchemaGeneratorConfigBuilder builder) {
private void applyToConfigBuilder(SchemaGeneratorGeneralConfigPart configPart) {
configPart.withDescriptionResolver(this.createTypePropertyResolver(Schema::description, description -> !description.isEmpty()));
configPart.withTitleResolver(this.createTypePropertyResolver(Schema::title, title -> !title.isEmpty()));
configPart.withAdditionalPropertiesResolver(this.createTypePropertyResolver(this::mapAdditionalPropertiesEnumValue, Objects::nonNull));

configPart.withCustomDefinitionProvider(new ExternalRefCustomDefinitionProvider());
configPart.withSubtypeResolver(new Swagger2SubtypeResolver());
Expand Down Expand Up @@ -179,6 +182,30 @@ protected boolean checkNullable(MemberScope<?, ?> member) {
.isPresent();
}

/**
* Derive the allowed type of a schema's additional properties from the given annotation.
*
* @param annotation annotation to check
* @return {@code Object.class} (if true or an external "$ref" is specified), {@code Void.class} (if forbidden) or {@code null} (if undefined)
*/
protected Type mapAdditionalPropertiesEnumValue(Schema annotation) {
if (!annotation.ref().isEmpty()) {
// prevent invalid combination of "$ref" with "additionalProperties": false
return Object.class;
}
switch (annotation.additionalProperties()) {
case TRUE:
// allow any additional properties
return Object.class;
case FALSE:
// block any additional properties
return Void.class;
default:
// fall-back on other configuration, e.g., as per Option.FORBIDDEN_ADDITIONAL_PROPERTIES_BY_DEFAULT
return null;
}
}

/**
* Determine whether the given field/method is deemed read-only based on {@code @Schema(accessMode = AccessMode.READ_ONLY)}.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,12 +133,14 @@ public String getName() {
}
}

@Schema(additionalProperties = Schema.AdditionalPropertiesValue.FALSE)
static class Foo {

@Schema(implementation = PersonReference.class, accessMode = Schema.AccessMode.WRITE_ONLY)
private Reference<Person> person;

@Schema(ref = "http://example.com/bar", accessMode = Schema.AccessMode.READ_ONLY)
@Schema(ref = "http://example.com/bar", accessMode = Schema.AccessMode.READ_ONLY,
additionalProperties = Schema.AdditionalPropertiesValue.TRUE)
private Object bar;

@Schema(anyOf = {Double.class, Integer.class})
Expand All @@ -147,6 +149,8 @@ static class Foo {
@Schema(oneOf = {Boolean.class, String.class})
private Object oneOfBooleanOrString;

// on a member, the "additionalProperties" attribute is ignored
@Schema(additionalProperties = Schema.AdditionalPropertiesValue.FALSE)
private TestClass test;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@

package com.github.victools.jsonschema.module.swagger2;

import com.github.victools.jsonschema.generator.ConfigFunction;
import com.github.victools.jsonschema.generator.FieldScope;
import com.github.victools.jsonschema.generator.InstanceAttributeOverrideV2;
import com.github.victools.jsonschema.generator.MethodScope;
import com.github.victools.jsonschema.generator.SchemaGeneratorConfigBuilder;
import com.github.victools.jsonschema.generator.SchemaGeneratorConfigPart;
import com.github.victools.jsonschema.generator.SchemaGeneratorGeneralConfigPart;
import java.util.function.BiFunction;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
Expand Down Expand Up @@ -69,6 +71,8 @@ public void testApplyToConfigBuilder() {

Mockito.verify(this.typesInGeneralConfigPart).withDescriptionResolver(Mockito.any());
Mockito.verify(this.typesInGeneralConfigPart).withTitleResolver(Mockito.any());
Mockito.verify(this.typesInGeneralConfigPart).withAdditionalPropertiesResolver(Mockito.any(ConfigFunction.class));
Mockito.verify(this.typesInGeneralConfigPart).withAdditionalPropertiesResolver(Mockito.any(BiFunction.class));
Mockito.verify(this.typesInGeneralConfigPart).withCustomDefinitionProvider(Mockito.any(ExternalRefCustomDefinitionProvider.class));
Mockito.verify(this.typesInGeneralConfigPart).withSubtypeResolver(Mockito.any(Swagger2SubtypeResolver.class));
Mockito.verify(this.typesInGeneralConfigPart).getDefinitionNamingStrategy();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,6 @@
"test": {
"$ref": "./TestClass-schema.json"
}
}
},
"additionalProperties": false
}

0 comments on commit 246449e

Please sign in to comment.