Skip to content

Commit

Permalink
Wrap refs with defaults in allOf (#1887)
Browse files Browse the repository at this point in the history
  • Loading branch information
srchase authored Jul 31, 2023
1 parent a121019 commit ef15e6d
Show file tree
Hide file tree
Showing 10 changed files with 203 additions and 9 deletions.
87 changes: 86 additions & 1 deletion docs/source-2.0/guides/converting-to-openapi.rst
Original file line number Diff line number Diff line change
Expand Up @@ -790,6 +790,89 @@ supportNonNumericFloats (``boolean``)
}
.. _generate-openapi-setting-disableDefaultValues:

disableDefaultValues (``boolean``)
Set to true to disable adding default values.

.. code-block:: json
{
"version": "2.0",
"plugins": {
"openapi": {
"service": "example.weather#Weather",
"disableDefaultValues": true
}
}
}
With this disabled, default values will not appear in the output:

.. code-block:: json
{
"Foo": {
"type": "object",
"properties": {
"bam": {
"type": "array",
"items": {
"type": "string"
}
},
"bar": {
"type": "number"
},
"bat": {
"$ref": "#/definitions/MyEnum"
},
"baz": {
"type": "string"
}
}
}
}
With this enabled (the default), default values will be added, with ``$ref``
pointers wrapped in an ``allOf``:

.. code-block:: json
{
"Foo": {
"type": "object",
"properties": {
"bam": {
"type": "array",
"items": {
"type": "string"
},
"default": []
},
"bar": {
"type": "number",
"default": 0
},
"bat": {
"allOf": [
{
"$ref": "#/definitions/MyEnum"
},
{
"default": "FOO"
}
]
},
"baz": {
"type": "string",
"default": ""
}
}
}
}
----------------
Security schemes
----------------
Expand Down Expand Up @@ -1438,7 +1521,9 @@ Amazon API Gateway limitations

The ``default`` property in OpenAPI is not currently supported by Amazon
API Gateway. The ``default`` property is automatically removed from OpenAPI
models when they are generated for Amazon API Gateway.
models when they are generated for Amazon API Gateway. Additionally, ``default``
values will not be set on ``$ref`` pointers or wrapped in an ``allOf`` as
described in :ref:`disableDefaultValues <generate-openapi-setting-disableDefaultValues>`.


-------------------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,6 @@ public List<ApiGatewayConfig.ApiType> getApiTypes() {
public void updateDefaultSettings(Model model, OpenApiConfig config) {
config.setAlphanumericOnlyRefs(true);
config.getDisableFeatures().add("default");
config.setDisableDefaultValues(true);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@
},
"components": {
"schemas": {
"DefaultEnum": {
"type": "string",
"enum": [
"FOO",
"BAR"
]
},
"HasDefaultRequestContent": {
"type": "object",
"properties": {
Expand All @@ -59,6 +66,9 @@
"items": {
"type": "string"
}
},
"baz": {
"$ref": "#/components/schemas/DefaultEnum"
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ $version: "2.0"

namespace example.smithy

use aws.protocols#httpChecksum
use aws.protocols#restJson1

@restJson1
Expand All @@ -20,9 +19,15 @@ operation HasDefault {
output := {
foo: String = ""
bar: StringList = []
baz: DefaultEnum = "FOO"
}
}

list StringList {
member: String
}

enum DefaultEnum {
FOO
BAR
}
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ public String toString() {
private boolean supportNonNumericFloats = false;
private boolean enableOutOfServiceReferences = false;
private boolean useIntegerType;
private boolean disableDefaultValues = false;

public JsonSchemaConfig() {
nodeMapper.setWhenMissingSetter(NodeMapper.WhenMissing.IGNORE);
Expand Down Expand Up @@ -406,6 +407,20 @@ public void setUseIntegerType(boolean useIntegerType) {
}


public boolean getDisableDefaultValues() {
return disableDefaultValues;
}

/**
* Set to true to disable default values on schemas, including wrapping $ref pointers in an `allOf`.
*
* @param disableDefaultValues True to disable setting default values.
*/
public void setDisableDefaultValues(boolean disableDefaultValues) {
this.disableDefaultValues = disableDefaultValues;
}


/**
* JSON schema version to use when converting Smithy shapes into Json Schema.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,13 @@ private Schema createRef(MemberShape member) {
if (converter.isInlined(member)) {
return member.accept(this);
} else {
Schema.Builder builder = Schema.builder().ref(converter.toPointer(member.getTarget()));
member.getTrait(DefaultTrait.class).ifPresent(trait -> builder.defaultValue(trait.toNode()));
return builder.build();
// Wrap the ref and default in an allOf if disableDefaultValues has been not been disabled on config.
if (member.hasTrait(DefaultTrait.class) && !converter.getConfig().getDisableDefaultValues()) {
Schema ref = Schema.builder().ref(converter.toPointer(member.getTarget())).build();
Schema def = Schema.builder().defaultValue(member.expectTrait(DefaultTrait.class).toNode()).build();
return Schema.builder().allOf(ListUtils.of(ref, def)).build();
}
return Schema.builder().ref(converter.toPointer(member.getTarget())).build();
}
}

Expand Down Expand Up @@ -317,8 +321,9 @@ private Schema.Builder updateBuilder(Shape shape, Schema.Builder builder) {
.map(EnumTrait::getEnumDefinitionValues)
.ifPresent(builder::enumValues);

shape.getTrait(DefaultTrait.class)
.ifPresent(trait -> builder.defaultValue(trait.toNode()));
if (shape.hasTrait(DefaultTrait.class) && !converter.getConfig().getDisableDefaultValues()) {
builder.defaultValue(shape.expectTrait(DefaultTrait.class).toNode());
}

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

@Test
public void appliesDefaults() {
public void appliesDefaultsByDefault() {
Model model = Model.assembler()
.addImport(getClass().getResource("default-values.smithy"))
.assemble()
Expand All @@ -703,4 +703,23 @@ public void appliesDefaults() {
IoUtils.toUtf8String(getClass().getResourceAsStream("default-values.jsonschema.v07.json")));
Node.assertEquals(document.toNode(), expected);
}

@Test
public void defaultsCanBeDisabled() {
Model model = Model.assembler()
.addImport(getClass().getResource("default-values.smithy"))
.assemble()
.unwrap();
JsonSchemaConfig config = new JsonSchemaConfig();
config.setDisableDefaultValues(true);
SchemaDocument document = JsonSchemaConverter.builder()
.config(config)
.model(model)
.build()
.convert();

Node expected = Node.parse(
IoUtils.toUtf8String(getClass().getResourceAsStream("default-values-disabled.jsonschema.v07.json")));
Node.assertEquals(document.toNode(), expected);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"definitions": {
"Foo": {
"type": "object",
"properties": {
"bam": {
"type": "array",
"items": {
"type": "string"
}
},
"bar": {
"type": "number"
},
"bat": {
"$ref": "#/definitions/TestEnum"
},
"baz": {
"type": "string"
}
}
},
"TestEnum": {
"type": "string",
"enum": [
"FOO",
"BAR"
]
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,28 @@
"type": "number",
"default": 0
},
"bat": {
"allOf": [
{
"$ref": "#/definitions/TestEnum"
},
{
"default": "FOO"
}
]
},
"baz": {
"type": "string",
"default": ""
}
}
},
"TestEnum": {
"type": "string",
"enum": [
"FOO",
"BAR"
]
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,15 @@ namespace smithy.example
structure Foo {
bar: Integer = 0
baz: String = ""
bam: StringList = []
bam: StringList = [],
bat: TestEnum = "FOO"
}

list StringList {
member: String
}

enum TestEnum {
FOO
BAR
}

0 comments on commit ef15e6d

Please sign in to comment.