Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for OpenAPI integer type #632

Merged
merged 1 commit into from
Nov 12, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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