Skip to content

Commit

Permalink
Support enum map keys on OpenAPI 3.1.0 (#1905)
Browse files Browse the repository at this point in the history
  • Loading branch information
srchase authored Aug 10, 2023
1 parent 665e00f commit b8999a4
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,32 @@

package software.amazon.smithy.openapi;

import java.util.Set;
import software.amazon.smithy.jsonschema.JsonSchemaVersion;
import software.amazon.smithy.utils.SetUtils;
import software.amazon.smithy.utils.SmithyInternalApi;

/**
* OpenAPI versions supported by the converter.
*/
public enum OpenApiVersion {

VERSION_3_0_2("3.0.2", false, JsonSchemaVersion.DRAFT07),
VERSION_3_1_0("3.1.0", true, JsonSchemaVersion.DRAFT2020_12);
VERSION_3_0_2("3.0.2", false, JsonSchemaVersion.DRAFT07,
SetUtils.of("propertyNames", "contentMediaType")),
VERSION_3_1_0("3.1.0", true, JsonSchemaVersion.DRAFT2020_12,
SetUtils.of("contentMediaType"));

private final String version;
private final boolean supportsContentEncodingKeyword;
private final JsonSchemaVersion jsonSchemaVersion;
// See https://swagger.io/docs/specification/data-models/keywords/ for 3.0.2.
private final Set<String> unsupportedKeywords;

OpenApiVersion(String version, boolean supportsContentEncodingKeyword, JsonSchemaVersion jsonSchemaVersion) {
OpenApiVersion(String version, boolean supportsContentEncodingKeyword, JsonSchemaVersion jsonSchemaVersion,
Set<String> unsupportedKeywords) {
this.version = version;
this.supportsContentEncodingKeyword = supportsContentEncodingKeyword;
this.jsonSchemaVersion = jsonSchemaVersion;
this.unsupportedKeywords = unsupportedKeywords;
}

@Override
Expand All @@ -46,6 +53,11 @@ public boolean supportsContentEncodingKeyword() {
return supportsContentEncodingKeyword;
}

@SmithyInternalApi
public Set<String> getUnsupportedKeywords() {
return unsupportedKeywords;
}

JsonSchemaVersion getJsonSchemaVersion() {
return jsonSchemaVersion;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import software.amazon.smithy.jsonschema.JsonSchemaConfig;
import software.amazon.smithy.jsonschema.JsonSchemaMapper;
import software.amazon.smithy.jsonschema.Schema;
Expand All @@ -35,7 +34,6 @@
import software.amazon.smithy.openapi.OpenApiConfig;
import software.amazon.smithy.openapi.model.ExternalDocumentation;
import software.amazon.smithy.utils.MapUtils;
import software.amazon.smithy.utils.SetUtils;

/**
* Applies OpenAPI extensions to a {@link Schema} using configuration settings
Expand All @@ -46,11 +44,6 @@
*/
public final class OpenApiJsonSchemaMapper implements JsonSchemaMapper {

/** See https://swagger.io/docs/specification/data-models/keywords/. */
private static final Set<String> UNSUPPORTED_KEYWORD_DIRECTIVES = SetUtils.of(
"propertyNames",
"contentMediaType");

@Override
public Schema.Builder updateSchema(Shape shape, Schema.Builder builder, JsonSchemaConfig config) {
getResolvedExternalDocs(shape, config)
Expand Down Expand Up @@ -93,7 +86,10 @@ public Schema.Builder updateSchema(Shape shape, Schema.Builder builder, JsonSche
}

// Remove unsupported JSON Schema keywords.
UNSUPPORTED_KEYWORD_DIRECTIVES.forEach(builder::disableProperty);
if (config instanceof OpenApiConfig) {
OpenApiConfig openApiConfig = (OpenApiConfig) config;
openApiConfig.getVersion().getUnsupportedKeywords().forEach(builder::disableProperty);
}

return builder;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -603,6 +603,7 @@ public void convertsToOpenAPI3_0_2() {

Node.assertEquals(result, expectedNode);
}

@Test
public void convertsToOpenAPI3_1_0() {
Model model = Model.assembler()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@
import software.amazon.smithy.model.shapes.ShortShape;
import software.amazon.smithy.model.shapes.StringShape;
import software.amazon.smithy.model.shapes.StructureShape;
import software.amazon.smithy.model.traits.BoxTrait;
import software.amazon.smithy.model.traits.DeprecatedTrait;
import software.amazon.smithy.model.traits.ExternalDocumentationTrait;
import software.amazon.smithy.model.traits.SensitiveTrait;
Expand All @@ -67,23 +66,6 @@ public void convertsModels() {
assertTrue(document.toNode().expectObjectNode().getMember("components").isPresent());
}

@Test
public void stripsUnsupportedKeywords() {
StringShape string = StringShape.builder().id("smithy.api#String").build();
MemberShape key = MemberShape.builder().id("smithy.example#Map$key").target("smithy.api#String").build();
MemberShape value = MemberShape.builder().id("smithy.example#Map$value").target("smithy.api#String").build();
MapShape shape = MapShape.builder().id("smithy.example#Map").key(key).value(value).build();
Model model = Model.builder().addShapes(string, shape, key, value).build();
SchemaDocument document = JsonSchemaConverter.builder()
.addMapper(new OpenApiJsonSchemaMapper())
.model(model)
.build()
.convertShape(shape);
Schema schema = document.getRootSchema();

assertFalse(schema.getPropertyNames().isPresent());
}

@Test
public void supportsExternalDocs() {
String key = "Homepage";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ blob FilePayload

@output
structure FooBarOutput {
bar: BoxedInteger
bar: BoxedInteger,
baz: MyMap
}

@error("client")
Expand All @@ -36,3 +37,18 @@ structure FooBarError {

@box
integer BoxedInteger

map MyMap {
key: MyEnum,
value: String
}

@enum([
{
value: "FOO"
},
{
value: "BAR"
}
])
string MyEnum
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,17 @@
"properties": {
"bar": {
"type": "number"
},
"baz": {
"$ref": "#/components/schemas/MyMap"
}
}
},
"MyMap": {
"type": "object",
"additionalProperties": {
"type": "string"
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,27 @@
"properties": {
"bar": {
"type": "number"
},
"baz": {
"$ref": "#/components/schemas/MyMap"
}
}
},
"MyEnum": {
"type": "string",
"enum": [
"FOO",
"BAR"
]
},
"MyMap": {
"type": "object",
"propertyNames": {
"$ref": "#/components/schemas/MyEnum"
},
"additionalProperties": {
"type": "string"
}
}
}
}
Expand Down

0 comments on commit b8999a4

Please sign in to comment.