Skip to content

Commit

Permalink
Add support for OpenAPI integer type
Browse files Browse the repository at this point in the history
This commit adds support for outputting an "integer" type instead
of a "number" type for byte, short, integer, and long shapes when
converting to OpenAPI.
  • Loading branch information
kstich committed Nov 12, 2020
1 parent 9af70ba commit ace3f74
Show file tree
Hide file tree
Showing 6 changed files with 414 additions and 8 deletions.
77 changes: 69 additions & 8 deletions docs/source/1.0/guides/converting-to-openapi.rst
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,8 @@ tools and vendors.

The following key-value pairs are supported:

.. _generate-openapi-setting-service:

service (``string``)
**Required**. The Smithy service :ref:`shape ID <shape-id>` to convert.
For example, ``smithy.example#Weather``.
Expand All @@ -189,6 +191,8 @@ service (``string``)
}
}
.. _generate-openapi-setting-protocol:

protocol (``string``)
The protocol shape ID to use when converting Smithy to OpenAPI.
For example, ``aws.protocols#restJson1``.
Expand All @@ -213,6 +217,8 @@ protocol (``string``)
}
}
.. _generate-openapi-setting-tags:

tags (``boolean``)
Whether or not to include Smithy :ref:`tags <tags-trait>` in the result
as `OpenAPI tags`_. The following example adds all tags in the Smithy
Expand All @@ -230,6 +236,8 @@ tags (``boolean``)
}
}
.. _generate-openapi-setting-supportedTags:

supportedTags (``[string]``)
Limits the exported ``tags`` to a specific set of tags. The value
must be a list of strings. This property requires that ``tags`` is set to
Expand All @@ -248,6 +256,8 @@ supportedTags (``[string]``)
}
}
.. _generate-openapi-setting-defaultBlobFormat:

defaultBlobFormat (``string``)
Sets the default format property used when converting blob shapes in
Smithy to strings in OpenAPI. Defaults to "byte", meaning Base64 encoded.
Expand All @@ -265,6 +275,8 @@ defaultBlobFormat (``string``)
}
}
.. _generate-openapi-setting-externalDocs:

externalDocs (``[string]``)
Limits the source of converted "externalDocs" fields to the specified
priority ordered list of names in an :ref:`externaldocumentation-trait`.
Expand All @@ -287,6 +299,8 @@ externalDocs (``[string]``)
}
}
.. _generate-openapi-setting-keepUnusedComponents:

keepUnusedComponents (``boolean``)
Set to ``true`` to prevent unused OpenAPI ``components`` from being
removed from the created specification.
Expand All @@ -303,6 +317,8 @@ keepUnusedComponents (``boolean``)
}
}
.. _generate-openapi-setting-jsonContentType:

jsonContentType (``string``)
Sets a custom media-type to associate with the JSON payload of
JSON-based protocols.
Expand All @@ -319,6 +335,8 @@ jsonContentType (``string``)
}
}
.. _generate-openapi-setting-forbidGreedyLabels:

forbidGreedyLabels (``boolean``)
Set to true to forbid greedy URI labels. By default, greedy labels will
appear as-is in the path generated for an operation. For example,
Expand All @@ -336,6 +354,8 @@ forbidGreedyLabels (``boolean``)
}
}
.. _generate-openapi-setting-onHttpPrefixHeaders:

onHttpPrefixHeaders (``string``)
Specifies what to do when the :ref:`httpPrefixHeaders-trait` is found in
a model. OpenAPI does not support ``httpPrefixHeaders``. By default, the
Expand All @@ -358,6 +378,8 @@ onHttpPrefixHeaders (``string``)
}
}
.. _generate-openapi-setting-ignoreUnsupportedTraits:

ignoreUnsupportedTraits (``boolean``)
Emits warnings rather than failing when unsupported traits like
``endpoint`` and ``hostLabel`` are encountered.
Expand All @@ -374,6 +396,8 @@ ignoreUnsupportedTraits (``boolean``)
}
}
.. _generate-openapi-setting-substitutions:

substitutions (``Map<String, any>``)
Defines a map of strings to any JSON value to find and replace in the
generated OpenAPI model.
Expand Down Expand Up @@ -409,6 +433,8 @@ substitutions (``Map<String, any>``)
}
}
.. _generate-openapi-setting-jsonAdd:

jsonAdd (``Map<String, Node>``)
Adds or replaces the JSON value in the generated OpenAPI document at the
given JSON pointer locations with a different JSON value. The value must
Expand Down Expand Up @@ -439,11 +465,34 @@ jsonAdd (``Map<String, Node>``)
}
}
.. _generate-openapi-setting-useIntegerType:

useIntegerType (``boolean``)
Set to true to use the "integer" type when converting ``byte``, ``short``,
``integer``, and ``long`` shapes to OpenAPI. Configuring this setting to
true, like the example below, is recommended.

By default, these shape types are converted to OpenAPI with a type of
"number".

.. code-block:: json
{
"version": "1.0",
"plugins": {
"openapi": {
"service": "smithy.example#Weather",
"useIntegerType": true
}
}
}
----------------------------------
JSON schema configuration settings
----------------------------------

.. _generate-openapi-jsonschema-setting-alphanumericOnlyRefs:

alphanumericOnlyRefs (``boolean``)
Creates JSON schema names that strip out non-alphanumeric characters.

Expand All @@ -456,6 +505,8 @@ alphanumericOnlyRefs (``boolean``)
``software.amazon.smithy:smithy-aws-apigateway-openapi`` is on the classpath
and ``apiGatewayType`` is not set to ``DISABLED``.

.. _generate-openapi-jsonschema-setting-useJsonName:

useJsonName (``boolean``)
Uses the value of the :ref:`jsonName-trait` when creating JSON schema
properties for structure and union shapes. This property MAY be
Expand All @@ -473,6 +524,8 @@ useJsonName (``boolean``)
}
}
.. _generate-openapi-jsonschema-setting-defaultTimestampFormat:

defaultTimestampFormat (``string``)
Sets the assumed :ref:`timestampFormat-trait` value for timestamps with
no explicit timestampFormat trait. The provided value is expected to be
Expand All @@ -491,6 +544,8 @@ defaultTimestampFormat (``string``)
}
}
.. _generate-openapi-jsonschema-setting-unionStrategy:

unionStrategy (``string``)
Configures how Smithy union shapes are converted to JSON Schema.

Expand All @@ -514,6 +569,8 @@ unionStrategy (``string``)
}
}
.. _generate-openapi-jsonschema-setting-mapStrategy:

mapStrategy (``string``)
Configures how Smithy map shapes are converted to JSON Schema.

Expand All @@ -539,6 +596,8 @@ mapStrategy (``string``)
}
}
.. _generate-openapi-jsonschema-setting-schemaDocumentExtensions:

schemaDocumentExtensions (``Map<String, any>``)
Adds custom top-level key-value pairs to the created OpenAPI specification.
Any existing value is overwritten.
Expand All @@ -560,6 +619,8 @@ schemaDocumentExtensions (``Map<String, any>``)
}
}
.. _generate-openapi-jsonschema-setting-disableFeatures:

disableFeatures (``[string]``)
Disables JSON schema and OpenAPI property names from appearing in the
generated OpenAPI model.
Expand Down Expand Up @@ -1169,19 +1230,19 @@ Next, you need to create and configure an ``OpenApiConverter``:
.. code-block:: java
import software.amazon.smithy.model.shapes.ShapeId;
import software.amazon.smithy.openapi.fromsmithy.OpenApiConstants;
import software.amazon.smithy.openapi.OpenApiConfig;
import software.amazon.smithy.openapi.fromsmithy.OpenApiConverter;
import software.amazon.smithy.openapi.fromsmithy.model.OpenApi;
import software.amazon.smithy.openapi.model.OpenApi;
OpenApiConverter converter = OpenApiConverter.create();
// Add any necessary settings...
converter.putSetting(OpenApiConstants.PROTOCOL, "aws.protocols#restJson1");
// Create a shape ID that points to the service.
ShapeId serviceShapeId = ShapeId.from("smithy.example#Weather");
// Add any necessary configuration settings.
OpenApiConfig config = new OpenApiConfig();
config.setService(ShapeId.from("smithy.example#Weather"));
converter.config(config);
OpenApi result = converter.convert(myModel, serviceShapeId);
// Generate the OpenAPI schema.
OpenApi result = converter.convert(myModel);
The conversion process is highly extensible through
``software.amazon.smithy.openapi.fromsmithy.CoreExtension``
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ public enum HttpPrefixHeadersStrategy {
private Map<String, Node> jsonAdd = Collections.emptyMap();
private List<String> externalDocs = ListUtils.of(
"Homepage", "API Reference", "User Guide", "Developer Guide", "Reference", "Guide");
private boolean useIntegerType;

public OpenApiConfig() {
super();
Expand Down Expand Up @@ -310,6 +311,23 @@ public void setExternalDocs(List<String> externalDocs) {
this.externalDocs = Objects.requireNonNull(externalDocs);
}

public boolean getUseIntegerType() {
return useIntegerType;
}

/**
* Set to true to use the "integer" type when converting {@code byte},
* {@code short}, {@code integer}, and {@code long} shapes to OpenAPI.
*
* <p>By default, these shape types are converted to OpenAPI with a type
* of "number".
*
* @param useIntegerType True to use "integer".
*/
public void setUseIntegerType(boolean useIntegerType) {
this.useIntegerType = useIntegerType;
}

/**
* Creates an OpenApiConfig from a Node value.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,14 @@ public Schema.Builder updateSchema(Shape shape, Schema.Builder builder, JsonSche
builder.putExtension("deprecated", Node.from(true));
}

// Handle OpenAPI's custom "integer" type.
// https://swagger.io/specification/#data-types
if (shape.isByteShape() || shape.isShortShape() || shape.isIntegerShape() || shape.isLongShape()) {
if (config instanceof OpenApiConfig && ((OpenApiConfig) config).getUseIntegerType()) {
builder.type("integer");
}
}

// Don't overwrite an existing format setting.
if (!builder.getFormat().isPresent()) {
if (shape.isIntegerShape()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,20 @@ public void doesNotPassThroughTagsWithEmptySupportedTagList() {
Node.assertEquals(result, expectedNode);
}

@Test
public void usesOpenApiIntegers() {
OpenApiConfig config = new OpenApiConfig();
config.setService(ShapeId.from("example.rest#RestService"));
config.setUseIntegerType(true);
ObjectNode result = OpenApiConverter.create()
.config(config)
.convertToNode(testService);
Node expectedNode = Node.parse(IoUtils.toUtf8String(
getClass().getResourceAsStream("test-service-integer.openapi.json")));

Node.assertEquals(result, expectedNode);
}

@Test
public void requiresProtocolsTrait() {
Exception thrown = Assertions.assertThrows(OpenApiException.class, () -> {
Expand Down
Loading

0 comments on commit ace3f74

Please sign in to comment.