AWS JSON 1.1 protocol#

This specification defines the aws.protocols#awsJson1_1 protocol.

aws.protocols#awsJson1_1 trait#

Summary
Adds support for an HTTP protocol that sends "POST" requests and responses with JSON documents.
Trait selector
service
Value type
Structure
See
Protocol tests

aws.protocols#awsJson1_1 is a structure that supports the following members:

Property Type Description
http [string] The priority ordered list of supported HTTP protocol versions.
eventStreamHttp [string] The priority ordered list of supported HTTP protocol versions that are required when using event streams with the service. If not set, this value defaults to the value of the http member. Any entry in eventStreamHttp MUST also appear in http.

Each entry in http and eventStreamHttp SHOULD be a valid Application-Layer Protocol Negotiation (ALPN) Protocol ID (for example, http/1.1, h2, etc). Clients SHOULD pick the first protocol in the list they understand when connecting to a service. A client SHOULD assume that a service supports http/1.1 when no http or eventStreamHttp values are provided.

The following example defines a service that uses aws.protocols#awsJson1_1.

$version: "2"

namespace smithy.example

use aws.protocols#awsJson1_1

@awsJson1_1
service MyService {
    version: "2020-02-05"
}

The following example defines a service that requires the use of h2 when using event streams.

$version: "2"

namespace smithy.example

use aws.protocols#awsJson1_1

@awsJson1_1(
    http: ["h2", "http/1.1"],
    eventStreamHttp: ["h2"]
)
service MyService {
    version: "2020-02-05"
}

The following example defines a service that requires the use of h2 or http/1.1 when using event streams, where h2 is preferred over http/1.1.

$version: "2"

namespace smithy.example

use aws.protocols#awsJson1_1

@awsJson1_1(
    http: ["h2", "http/1.1"],
    eventStreamHttp: ["h2", "http/1.1"]
)
service MyService {
    version: "2020-02-05"
}

The following example defines a service that requires the use of h2 for all requests, including event streams.

$version: "2"

namespace smithy.example

use aws.protocols#awsJson1_1

@awsJson1_1(http: ["h2"])
service MyService {
    version: "2020-02-05"
}

Supported traits#

The awsJson1_1 protocol supports the following traits that affect serialization:

Trait Description
cors Indicates that the service supports CORS.
endpoint Configures a custom operation endpoint.
hostLabel Binds a top-level operation input structure member to a label in the hostPrefix of an endpoint trait.
timestampFormat Defines a custom timestamp serialization format.
requestCompression Indicates that an operation supports compressing requests from clients to services.

Protocol Behaviors#

Every request for the awsJson1_1 protocol MUST be sent to the root URL (/) using the HTTP "POST" method.

The awsJson1_1 protocol does not support custom HTTP bindings. HTTP binding traits MUST be ignored if they are present.

The awsJson1_1 protocol uses the following headers:

Header Required Description
Content-Type true This header has a static value of application/x-amz-json-1.1.
Content-Length true The standard Content-Length header defined by RFC 7230#section-3.3.2.
X-Amz-Target true for requests

The value of this header is the shape name of the service's Shape ID joined to the shape name of the operation's Shape ID, separated by a single period (.) character.

For example, the value for the operation ns.example#MyOp of the service ns.example#MyService is MyService.MyOp.

Default value serialization#

  1. To avoid information disclosure, serializers SHOULD omit the default value of structure members that are marked with the internal trait.
  2. Client deserializers SHOULD attempt to error correct structures that omit a @required member by filling in a default zero value for the member. Error correction allows clients to continue to function while the server is in error.

Shape serialization#

The awsJson1_1 protocol serializes all shapes into a JSON document body with no HTTP bindings supported. The following table shows how to convert each shape type:

Smithy type JSON type
blob JSON string value that is base64 encoded.
boolean JSON boolean
byte JSON number
short JSON number
integer JSON number
long JSON number
float JSON number for numeric values. JSON strings for NaN, Infinity, and -Infinity.
double 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 truncate the value or be unable to parse numbers that exceed the size of a double.
bigInteger JSON number. Unfortunately, this protocol serializes bigInteger shapes as a normal JSON number. Many JSON parsers will either truncate the value or be unable to parse numbers that exceed the size of a double.
string JSON string
timestamp JSON number (default). This protocol uses epoch-seconds, also known as Unix timestamps, in JSON payloads represented as a double. However, the timestampFormat MAY be used to customize timestamp serialization.
document Any JSON value
list JSON array
map JSON object
structure JSON object. Each member value provided for the structure is serialized as a JSON property where the property name is the same as the member name. The jsonName trait can be used to serialize a property using a custom name.
union JSON object. A union is serialized identically as a structure shape, but only a single member can be set to a non-null value. Deserializers MUST ignore an unrecognized __type member if present.

Empty body serialization#

When an operation has no modeled input or if no input parameters are provided, a client MUST send an empty JSON object ({}) as the request body. Server implementations MUST also accept empty request bodies.

When an operation has no modeled output or no output parameters are provided, server implementations SHOULD send an empty response body. The server MUST still send the protocol's Content-Type header in this case. Clients MUST also accept an empty JSON object as the response body.

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 awsJson1_1 protocol treats those special values as strings with the following values:

Special Value String Value
Not a number NaN
Positive infinity Infinity
Negative infinity -Infinity

Operation error serialization#

Error responses in the awsJson1_1 protocol are serialized identically to standard responses with one additional component to distinguish which error is contained. New server-side protocol implementations SHOULD use a body field named __type. The component MUST be one of the following: an additional header with the name X-Amzn-Errortype, a body field with the name code, or a body field named __type. The value of this component SHOULD contain the error's shape name.

Legacy server-side protocol implementations sometimes include different information in this value. All client-side implementations SHOULD support sanitizing the value to retrieve the disambiguated error type using the following steps:

  1. If a : character is present, then take only the contents before the first : character in the value.
  2. If a # character is present, then take only the contents after the first # character in the value.

All of the following error values resolve to FooError:

  • FooError
  • FooError:http://internal.amazon.com/coral/com.amazon.coral.validate/
  • aws.protocoltests.restjson#FooError
  • aws.protocoltests.restjson#FooError:http://internal.amazon.com/coral/com.amazon.coral.validate/

Differences between awsJson1_0 and awsJson1_1#

There are two difference between awsJson1_0 and awsJson1_1. First, the static value of the Content-Type header is different. In awsJson1_0 it MUST be application/x-amz-json-1.0 and in awsJson1_1 it MUST be application/x-amz-json-1.1.

Second, error type serialization is different. In awsJson1_0, servers SHOULD send the error shape's full Shape ID in the __type field of the body. In awsJson1_1, servers SHOULD only send the error's shape name. However, clients MUST accept either behavior for both protocols. See Operation error serialization for full details on how to deserialize errors for awsJson1_1.

Protocol compliance tests#

A full compliance test suite is provided and SHALL be considered a normative reference: https://github.com/smithy-lang/smithy/tree/main/smithy-aws-protocol-tests/model/awsJson1_1

These compliance tests define a model that is used to define test cases and the expected serialized HTTP requests and responses for each case.

TODO: Add event stream handling specifications.

Error shape renaming#

By default, Smithy permits renaming shapes to disambiguate shape ID conflicts in the service closure via the rename property. However, services using this protocol are not allowed to rename error shapes (shapes with error trait applied).

Client-side implementations rely on the response body field code or __type to resolve the error type. Server-side implementations of this protocol will only send the shape name for the response body field.

When there are conflicting shape IDs smithy.service#ServiceError and smithy.other#ServiceError, the server will only send the shape name ServiceError. Clients will not be able to resolve the correct error type without the namespace.

Server-side implementations of this protocol don't serialize renamed shape names. As a result, renaming will not resolve the conflicting shape IDs issue, and hence it is not permitted.