Skip to content

Serialization and Protocol Traits

Juli Tera edited this page Apr 19, 2024 · 3 revisions

This wiki contains a mapping between Smithy Serialization and Protocol traits and generated Ruby code.

protocolDefinition trait

A meta-trait that marks a trait as a @protocolDefinition trait. Traits that are marked with this trait are applied to service shapes to define the protocols supported by a service. This trait does not influence code generation.

/// An example JSON protocol.
@protocolDefinition
@trait(selector: "service")
structure jsonExample {}

See Smithy Documentation for more details.

jsonName trait

Allows a serialized object property name in a JSON document to differ from a structure member name used in the model. In builders and parsers, the jsonName value is used in place of a symbolized and snake cased member name.

structure MyOperationInputOutput {
    @jsonName("RenamedMember")
    Value: String,
}

The generated code is:

# builders.rb
class MyOperation
  def self.build(http_req, input)
    ...
    data = {}
    data['RenamedMember'] = input[:value] unless input[:value].nil?
    ...
  end
end

# parsers.rb
class MyOperation
  def self.parse(http_resp)
    data = Types::MyOperationOutput.new
    map = Hearth::JSON.parse(http_resp.body.read)
    data.value = map['RenamedMember']
    data
  end
end

See Smithy Documentation for more details.

mediaType trait

Describes the contents of a blob or string shape using a design-time media type as defined by RFC 6838 (for example, application/json). The @mediaType trait is used in three ways:

  1. It determines the Content-Type header when it is applied to a member that also has the @httpPayload trait. In this case, the Content-Type header is set to the mediaType value in the request builder.
  2. If the shape is targeted by the @httpHeader trait, the value is base64 encoded.
  3. Otherwise, it is used to aid documentation, validation, or add special cased helper methods to work with the media type. The trait is entirely optional for these cases.

Special cased helpers will not be supported at this time.

Example of using @mediaType and @httpPayload traits:

structure MyOperationInput {
    @httpPayload
    blob: BlobValue,
}

@mediaType("application/foo")
blob BlobValue

The generated code:

# builders.rb
class MyOperation
  def self.build(http_req, input:)
    ...
    http_req.headers['Content-Type'] = 'application/foo'
  end
end

Example of using @mediaType and @httpHeader traits:

structure MyOperationInput {
    @httpHeader("X-Foo")
    foo: FooValue,
}

@mediaType("application/json")
string FooValue

The generated code:

# builders.rb
class MyOperation
  def self.build(http_req, input:)
    ...
    http_req.headers['X-Foo'] = ::Base64::encode64(input[:foo]).strip unless input[:foo].nil? || input[:foo].empty?
  end
end

See Smithy Documentation for details.

timestampFormat trait

Defines a custom timestamp serialization format. For each timestamp format, the builders will convert a Time object to the protocol’s format, and the parsers will convert to a Time object from the protocol’s format. The Hearth::TimeHelper module is used for converting. The following formats are supported:

  • date-time format - In the builder, the to_date_time method is used to convert a Time object to date-time. In the parser, the Time.parse method is used to convert back into a Time object.
  • http-date format - In the builder, the to_http_date method is used to convert a Time object to http-date. In the parser, the Time.parse method is used to convert back into a Time object.
  • epoch-seconds format - In the builder, the to_epoch_seconds method is used to convert a Time object to epoch-seconds. In the parser, the Time.at method is used to convert back into a Time object.
structure MyOperationInputOutput {
    @timestampFormat("http-date")
    HttpdateTimestamp: Timestamp
}

The generated code is:

# builders.rb
class MyOperation
  def self.build(http_req, input:)
    ...
    data = {}
    data[:httpdate_timestamp] = Hearth::TimeHelper.to_http_date(input[:httpdate_timestamp]) unless input[:httpdate_timestamp].nil?
    ...
  end
end

# parsers.rb
class MyOperation
  def self.parse(http_resp)
    data = Types::MyOperationOutput.new
    map = Hearth::JSON.parse(http_resp.body.read)
    data.httpdate_timestamp = Time.parse(map['httpdate_timestamp']) if map['httpdate_timestamp']
  end
end

See Smithy Documentation for more details.