6. Constraint traits#

Constraint traits are used to constrain the values that can be provided for a shape. Constraint traits are for validation only and SHOULD NOT impact the types signatures of generated code.

See also

required trait, a type refinement trait that also functions like a constraint.

6.1. Constraint trait enforcement#

Constraint traits SHOULD be enforced after deserializing input. For example, when a server deserializes a request from a client, the server SHOULD enforce any defined constraint traits and reject the request if appropriate.

Constraint traits SHOULD NOT be enforced when serializing shapes or when deserializing output. For example, when returning a response from a server to a client, failing to serialize a response due to a constraint trait violation would prevent a client from observing a state change of the server and would provide no real recourse for the client or server to recover.

6.2. idRef trait#

Summary

Indicates that a string value MUST contain a valid absolute shape ID.

The idRef trait is used primarily when declaring trait shapes in a model. A trait shape that targets a string shape with the idRef trait indicates that when the defined trait is applied to a shape, the value of the trait MUST be a valid shape ID. The idRef trait can also be applied at any level of nesting on shapes referenced by trait shapes.

Trait selector

:test(string, member > string)

A string shape or a member that targets a string shape

Value type
structure

The idRef trait is a structure that supports the following optional members:

Property Type Description
failWhenMissing boolean When set to true, the shape ID MUST target a shape that can be found in the model.
selector string

Defines the selector that the resolved shape, if found, MUST match.

selector defaults to * when not defined.

errorMessage string

Defines a custom error message to use when the shape ID cannot be found or does not match the selector.

A default message is generated when errorMessage is not defined.

To illustrate an example, a custom trait named integerRef is defined. This trait can be attached to any shape, and the value of the trait MUST contain a valid shape ID that targets an integer shape in the model.

$version: "2"
namespace smithy.example

@trait
@idRef(failWhenMissing: true, selector: "integer")
string integerRef

Given the following model,

$version: "2"
namespace smithy.example

@integerRef(NotFound)
string InvalidShape1

@integerRef(String)
string InvalidShape2

@integerRef("invalid-shape-id!")
string InvalidShape3

@integerRef(Integer)
string ValidShape

@integerRef(MyShape)
string ValidShape2

integer MyShape
  • InvalidShape1 is invalid because the "NotFound" shape cannot be found in the model.
  • InvalidShape2 is invalid because "smithy.api#String" targets a string which does not match the "integer" selector.
  • InvalidShape3 is invalid because "invalid-shape-id!" is not a syntactically correct absolute shape ID.
  • ValidShape is valid because "smithy.api#Integer" targets an integer.
  • ValidShape2 is valid because "MyShape" is a relative ID that targets smithy.example#MyShape.

6.3. length trait#

Summary
Constrains a shape to minimum and maximum number of elements or size.
Trait selector

:test(list, map, string, blob, member > :is(list, map, string, blob))

Any list, map, string, or blob; or a member that targets one of these shapes

Value type
structure

The length trait is a structure that contains the following members:

Property Type Description
min number Integer value that represents the minimum inclusive length of a shape.
max number Integer value that represents the maximum inclusive length of a shape.

At least one of min, max is required.

The following table describes what a length trait constrains when applied to the corresponding shape:

Shape Length constrains
list The number of members
map The number of key-value pairs
string The number of Unicode scalar values
blob The size of the blob in bytes
@length(min: 1, max: 10)
string MyString

@length(min: 1)
string NonEmptyString

@length(max: 10)
string StringLessThanOrEqualToTen

6.4. pattern trait#

Summary
Restricts string shape values to a specified regular expression.
Trait selector

:test(string, member > string)

A string or a member that targets a string

Value type
string

Smithy regular expressions MUST be valid regular expressions according to the ECMA 262 regular expression dialect. Patterns SHOULD avoid the use of conditionals, directives, recursion, lookahead, look-behind, back-references, and look-around in order to ensure maximum compatibility across programming languages.

@pattern("^[A-Za-z]+$")
string Alphabetic

Warning

Pattern values should be chosen with care, as regex evaluation can be expensive. Regular expressions SHOULD be tested against a range of potentially malformed inputs to ensure that the execution of the regular expression match does not lead to a potential denial of service. See OWASP Regular expression Denial of Service for more information.

Important

The pattern trait does not implicitly add a leading ^ or trailing $ to match an entire string. For example, @pattern("\\w+") matches both "hello" and "!hello!" because it requires that just part of the string matches the regular expression, whereas @pattern("^\\w+$") requires that the entire string matches the regular expression.

Note

Pattern values that contain \ need to escape it. For example, the regular expression ^\w+$ would be specified as @pattern("^\\w+$").

@pattern("\\w+")
string ContainsWords

6.5. private trait#

Summary
Prevents models defined in a different namespace from referencing the targeted shape.
Trait selector
*
Value type
Annotation trait

Shapes marked as private cannot be accessed outside of the namespace in which the shape is defined. The private trait is meant only to control access from within the model itself and SHOULD NOT influence code-generation of the targeted shape.

Consider the following model:

$version: "2"
namespace smithy.example

@private
string PrivateString

The following model is invalid because it attempts to refer to PrivateString from another namespace:

$version: "2"
namespace smithy.example.other

list StringList {
    member: PrivateString
}

6.6. range trait#

Summary
Restricts allowed values of number shapes within an acceptable lower and upper bound.
Trait selector

:test(number, member > number)

A number or a member that targets a number

Value type
structure

The range trait is a structure that contains the following members:

Property Type Description
min bigDecimal Specifies the allowed inclusive minimum value.
max bigDecimal Specifies the allowed inclusive maximum value.

At least one of min or max is required. min and max accept both integers and real numbers. Real numbers may only be applied to float, double, or bigDecimal shapes. min and max MUST fall within the allowable range of the targeted numeric shape to which it is applied.

@range(min: 1, max: 10)
integer OneToTen

@range(min: 1)
integer GreaterThanOne

@range(max: 10)
integer LessThanTen

6.7. uniqueItems trait#

Summary
Requires the items in a list to be unique based on Value equality.
Trait selector

list :not(> member ~> :is(float, double, document))

A list that does not transitively contain floats, doubles, or documents

Conflicts with
Value type
Annotation trait.
@uniqueItems
list MyList {
    member: String
}

6.7.1. Value equality#

Two values are considered equal if:

  • They are the same type.
  • Both are strings and are the same codepoint-for-codepoint.
  • Both are blobs and are the same byte-for-byte.
  • Both are booleans and are both true or are both false.
  • Both are timestamps and refer to the same instant in time.
  • Both are lists and have an equal value item-for-item. Note that sets, a deprecated data type, are treated exactly like lists.
  • Both are maps, have the same number of entries, and each key value pair in one map has an equal key value pair in the other map. The order of entries does not matter.
  • Both are numbers of the same type and have the same mathematical value.
  • Both are structures of the same type and have the same members with equal values.
  • Both are unions of the same type, are set to the same member, and the set members have the same value.

Note

Floats, doubles, and documents are not allowed in @uniqueItems lists because they only allow for partial equivalence and require special care to determine if two values are considered equal.

6.8. enum trait#

Danger

This trait is deprecated. An enum shape should be used instead.

Summary
Constrains the acceptable values of a string to a fixed set.
Trait selector
string :not(enum)
Value type
list of enum definition structures.

An enum definition is a structure that supports the following members:

Property Type Description
value string Required. Defines the enum value that is sent over the wire. Values MUST NOT be empty. Values MUST be unique across all enum definitions in an enum trait.
name string

Defines a constant name that can be used in programming languages to reference an enum value. A name is not required, though their use is strongly encouraged to help tools like code generators safely and reliably create symbols that represent specific values.

Validation constraints:

  • Names MUST start with an upper or lower case ASCII Latin letter (A-Z or a-z), or the ASCII underscore (_) and be followed by zero or more upper or lower case ASCII Latin letters (A-Z or a-z), ASCII underscores (_), or ASCII digits (0-9). That is, names MUST match the following regular expression: ^[a-zA-Z_]+[a-zA-Z_0-9]*$.
  • The following stricter rules are recommended for consistency: Enum constant names SHOULD NOT contain any lowercase ASCII Latin letters (a-z) and SHOULD NOT start with an ASCII underscore (_). That is, enum names SHOULD match the following regular expression: ^[A-Z]+[A-Z_0-9]*$.
  • Names MUST be unique across all enum definitions of an enum trait.
  • If any enum definition has a name, then all entries in the enum trait MUST have a name.
documentation string Defines documentation about the enum value in the CommonMark format.
tags [string] Attaches a list of tags that allow the enum value to be categorized and grouped.
deprecated boolean Whether the enum value should be considered deprecated for consumers of the Smithy model.

Note

While the changeStringEnumsToEnumShapes transform can be used to convert to an enum shape, it is recommended to use the enum shape instead.