Skip to content

Describe and support non-numeric floats #828

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

Merged
merged 11 commits into from
Jun 17, 2021
57 changes: 57 additions & 0 deletions docs/source/1.0/guides/converting-to-openapi.rst
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,7 @@ useIntegerType (``boolean``)
}
}


----------------------------------
JSON schema configuration settings
----------------------------------
Expand Down Expand Up @@ -663,6 +664,62 @@ disableFeatures (``[string]``)
}


.. _generate-openapi-setting-supportNonNumericFloats:

supportNonNumericFloats (``boolean``)
Set to true to add support for NaN, Infinity, and -Infinity in float
and double shapes. These values will be serialized as strings. The
JSON Schema document will be updated to refer to them as a "oneOf" of
number and string.

By default, these non-numeric values are not supported.

.. code-block:: json

{
"version": "1.0",
"plugins": {
"openapi": {
"service": "smithy.example#Weather",
"supportNonNumericFloats": true
}
}
}

When this is disabled (the default), references to floats/doubles will
look like this:

.. code-block: json

{
"floatMember": {
"type": "number"
}
}

With this enabled, references to floats/doubles will look like this:

.. code-block:: json

{
"floatMember": {
"oneOf": [
{
"type": "number"
},
{
"type": "string",
"enum": [
"NaN",
"Infinity",
"-Infinity"
]
}
]
}
}


----------------
Security schemes
----------------
Expand Down
4 changes: 4 additions & 0 deletions docs/source/1.0/spec/aws/aws-ec2-query-protocol.rst
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,10 @@ serialized in the response.
</Errors>


.. _ec2Query-non-numeric-float-serialization:
.. include:: non-numeric-floats.rst.template


.. _ec2Query-compliance-tests:

-------------------------
Expand Down
9 changes: 7 additions & 2 deletions docs/source/1.0/spec/aws/aws-json.rst.template
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,11 @@ to convert each shape type:
* - ``long``
- JSON number
* - ``float``
- JSON number
- JSON number for numeric values. JSON strings for ``NaN``, ``Infinity``,
and ``-Infinity``.
* - ``double``
- JSON number
- JSON number for numeric values. JSON strings for ``NaN``, ``Infinity``,
and ``-Infinity``
* - ``bigDecimal``
- JSON number. Unfortunately, this protocol serializes bigDecimal
shapes as a normal JSON number. Many JSON parsers will either
Expand Down Expand Up @@ -145,6 +147,9 @@ still send the protocol's ``Content-Type`` header in this case. Clients MUST
also accept an empty JSON object as the response body.


.. include:: non-numeric-floats.rst.template


-----------------------------
Operation error serialization
-----------------------------
Expand Down
4 changes: 4 additions & 0 deletions docs/source/1.0/spec/aws/aws-query-protocol.rst
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,10 @@ is used to distinguish which specific error is serialized in the response.
</ErrorResponse>


.. _awsQuery-non-numeric-float-serialization:
.. include:: non-numeric-floats.rst.template


.. _awsQuery-error-response-code:

Error HTTP response code resolution
Expand Down
10 changes: 8 additions & 2 deletions docs/source/1.0/spec/aws/aws-restjson1-protocol.rst
Original file line number Diff line number Diff line change
Expand Up @@ -246,9 +246,11 @@ JSON shape serialization
* - ``long``
- JSON number
* - ``float``
- JSON number
- JSON number for numeric values. JSON strings for ``NaN``, ``Infinity``,
and ``-Infinity``
* - ``double``
- JSON number
- JSON number for numeric values. JSON strings for ``NaN``, ``Infinity``,
and ``-Infinity``
* - ``bigDecimal``
- JSON number. Unfortunately, this protocol serializes bigDecimal
shapes as a normal JSON number. Many JSON parsers will either
Expand Down Expand Up @@ -297,6 +299,10 @@ serialization formats and and behaviors described for each trait are supported
as defined in the ``aws.protocols#restJson1`` protocol.


.. |quoted shape name| replace:: ``aws.protocols#restJson1``
.. include:: non-numeric-floats.rst.template


.. restJson1-errors:

-----------------------------
Expand Down
4 changes: 4 additions & 0 deletions docs/source/1.0/spec/aws/aws-restxml-protocol.rst
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,10 @@ serialization formats and and behaviors described for each trait are supported
as defined in the ``aws.protocols#restXml`` protocol.


.. |quoted shape name| replace:: ``aws.protocols#restXml``
.. include:: non-numeric-floats.rst.template


.. _restXml-errors:

-----------------------------
Expand Down
21 changes: 21 additions & 0 deletions docs/source/1.0/spec/aws/non-numeric-floats.rst.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
------------------------------------------
Non-numeric float and double serialization
------------------------------------------

Smithy floats and doubles are defined by IEEE-754, which includes special values
for "not a number" and both positive and negative infinity. Unless otherwise
specified, the |quoted shape name| protocol treats those special values as
strings with the following values:

.. list-table::
:header-rows: 1
:widths: 50 50

* - Special Value
- String Value
* - Not a number
- ``NaN``
* - Positive infinity
- ``Infinity``
* - Negative infinity
- ``-Infinity``
10 changes: 6 additions & 4 deletions docs/source/1.0/spec/core/model.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2334,11 +2334,13 @@ target from traits and how their values are defined in
- number
- The value MUST fall within the range of -2^63 to (2^63)-1.
* - float
- number
- A normal JSON number.
- string | number
- The value MUST be either a normal JSON number or one of the following
string values: ``"NaN"``, ``"Infinity"``, ``"-Infinity"``.
* - double
- number
- A normal JSON number.
- string | number
- The value MUST be either a normal JSON number or one of the following
string values: ``"NaN"``, ``"Infinity"``, ``"-Infinity"``.
* - bigDecimal
- string | number
- bigDecimal values can be serialized as strings to avoid rounding
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package software.amazon.smithy.aws.apigateway.openapi;

import org.junit.jupiter.api.Test;
import software.amazon.smithy.model.Model;
import software.amazon.smithy.model.node.Node;
import software.amazon.smithy.model.node.ObjectNode;
import software.amazon.smithy.model.shapes.ShapeId;
import software.amazon.smithy.openapi.OpenApiConfig;
import software.amazon.smithy.openapi.fromsmithy.OpenApiConverter;
import software.amazon.smithy.utils.IoUtils;

public class NonNumericFloatsTest {
@Test
public void handlesNonNumericFloats() {
Model model = Model.assembler(getClass().getClassLoader())
.discoverModels(getClass().getClassLoader())
.addImport(getClass().getResource("non-numeric-floats.json"))
.assemble()
.unwrap();
OpenApiConfig config = new OpenApiConfig();
config.setService(ShapeId.from("example.smithy#MyService"));
config.setSupportNonNumericFloats(true);
ObjectNode result = OpenApiConverter.create().config(config).convertToNode(model);
Node expectedNode = Node.parse(IoUtils.toUtf8String(
getClass().getResourceAsStream("non-numeric-floats.openapi.json")));

Node.assertEquals(result, expectedNode);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"smithy": "1.0",
"shapes": {
"example.smithy#MyService": {
"type": "service",
"version": "2006-03-01",
"operations": [
{
"target": "example.smithy#MyOperation"
}
],
"traits": {
"aws.protocols#restJson1": {}
}
},
"example.smithy#MyOperation": {
"type": "operation",
"input": {
"target": "example.smithy#MyOperationInput"
},
"traits": {
"smithy.api#http": {
"uri": "/foo",
"method": "POST"
}
}
},
"example.smithy#MyOperationInput": {
"type": "structure",
"members": {
"floatMember": {
"target": "smithy.api#Float"
},
"doubleMember": {
"target": "smithy.api#Double"
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
{
"openapi": "3.0.2",
"info": {
"title": "MyService",
"version": "2006-03-01"
},
"paths": {
"/foo": {
"post": {
"operationId": "MyOperation",
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/MyOperationRequestContent"
}
}
}
},
"responses": {
"200": {
"description": "MyOperation response"
}
}
}
}
},
"components": {
"schemas": {
"MyOperationRequestContent": {
"type": "object",
"properties": {
"floatMember": {
"oneOf": [
{
"type": "number",
"format": "float"
},
{
"type": "string",
"enum": [
"NaN",
"Infinity",
"-Infinity"
]
}
],
"nullable": true
},
"doubleMember": {
"oneOf": [
{
"type": "number",
"format": "double"
},
{
"type": "string",
"enum": [
"NaN",
"Infinity",
"-Infinity"
]
}
],
"nullable": true
}
}
}
}
}
}
Loading