Skip to main content

Async + RAML Data Types in AMF

Technical Document

This is a technical document, this information is intended for experienced users

Within the Async specification it is possible to use RAML data types to define a payload, taking into account that the schema format is specified accordingly. Both specifications have their own distinct referencing and modularization mechanisms, and it is not clear where to draw the line to determine where one specification stops, and the other one starts. This document will describe how to use RAML types in Async when using AMF.

Referencing external RAML content using $ref#

In order to support referencing RAML content in external files, AMF allows the use of the $ref mechanism present in Async. This enables referencing data type fragments, data types present in libraries, as well as any RAML content present in yaml or json files.

However, the usage of $ref in this scenario has some restrictions. Given that the payload content must comply with RAML, the $ref may only be used at the root of the payload definition as an exception to the RAML specification. Its target content must be valid structurally according to the relevant RAML specification:

β€˜$ref’ at root of payload (Valid)
schemaFormat: application/RAML+yaml;version=1.0
payload:
$ref: β€œ...” # must reference raml content
β€˜$ref’ nested within RAML content (Invalid)
schemaFormat: application/raml+yaml;version=1.0
payload:
type: object
properties:
user:
$ref: β€œ...” # '$ref' is not valid in RAML

The following section shows all supported use cases when using this referencing mechanism, adding additional comments if necessary.

Reference to data type fragments#

The data type fragment must be self-contained, meaning it cannot depend on any definition made in the root API. The following example is valid for this use case.

Async API
schemaFormat: application/raml+yaml;version=1.0
payload:
$ref: external-data-type.raml
RAML data type fragment (external-data-type.raml)
#%RAML 1.0 DataType
type: object
properties:
a: string | object

The following referenced data type is invalid as it is not self-contained, meaning the data type fragment depends on type definitions which will not be resolved in the root API. Due to known limitations this API will not return any validations (error or warning), but the reference to the type Other inside the data type will not be made, leaving it unresolved.

Async API
components:
schemas:
Other: ...
channels:
users/signup:
subscribe:
message:
schemaFormat: application/raml+yaml;version=1.0
payload:
$ref: external-data-type.raml
RAML data type fragment (external-data-type.raml)
#%RAML 1.0 DataType
type: object
properties:
a: Other

Use of relative pointers to nested content within the data type fragment is not supported, like in the following invalid example:

schemaFormat: application/raml+yaml;version=1.0
payload:
$ref: external-data-type.raml#/properties/a

Reference to types in library fragments#

For the case of libraries, type definitions can be referenced using the following fixed pointer: {lib}#/types/{typeName}. When referencing types defined in a library, the included content will have context of other type definitions present in the original library. This can be seen in the following valid example where the type User references another type present in the external library.

Async API
schemaFormat: application/raml+yaml;version=1.0
payload:
$ref: ../external-library.raml#/types/User
RAML library fragment (external-library.raml)
#%RAML 1.0 Library
types:
User:
type: Other | string
Other:
type: string

The external library must be self-contained, meaning it cannot depend on types defined in the root API. In the following invalid example, the library depends on the definition of the type Other, which will not be resolved from the definitions present in the main API.

Async API
components:
schemas:
Other: ...
channels:
users/signup:
subscribe:
message:
schemaFormat: application/raml+yaml;version=1.0
payload:
$ref: ../external-library.raml#/types/User
RAML library fragment (external-library.raml)
#%RAML 1.0 Library
types:
User:
type: Other | string

Reference to external yaml/json files#

When referencing external yaml or json files, the $ref inlines the content. Relative json pointers can be used to reference content that is nested within the file, but taking into account the following limitation:

When referencing to external yaml/json files

the external file must not be a known RAML fragment or API specification.

The following case is a valid reference making use of relative json pointers.

Async API
schemaFormat: application/raml+yaml;version=1.0
payload:
$ref: external-yaml.yaml#/definitions/User
Yaml file (external-yaml.yaml)
definitions:
User:
type: string | object

As previously mentioned, when the target file is a known RAML fragment or API specification free use of relative json pointers is not supported. The following example shows an invalid example when using relative json pointer to reference an external RAML specification:

Async API
schemaFormat: application/raml+yaml;version=1.0
payload:
$ref: ../api.raml#/types/User
External RAML API (api.raml)
#%RAML 1.0
title: Instagram API
types:
User:
type: object

Inlined RAML types#

The simplest way to define a RAML type in Async is by defining your content inlined under the payload facet while using the appropriate schema format like so:

schemaFormat: application/raml+yaml;version=1.0
payload: # The following is a RAML data type
type: object
properties:
a: object | string
additionalProperties: false

All content within the payload will be considered strictly RAML, except when using β€˜$ref’ at the root of the payload (see the previous section for more details).

Isolated RAML context#

When defining inlined types, its context is fully restricted from the content defined outside the payload facet. This means that any reference to content defined in the components facet of the main Async API will not be resolved.

Referencing types defined in async API components (invalid)
components:
schemas:
User: ...
channels:
users/signup:
subscribe:
message:
schemaFormat: application/raml+yaml;version=1.0
payload:
type: User #unresolved reference

Limited RAML referencing mechanism#

RAML has its own referencing mechanism to include content from external files using a reserved yaml tag !include. AMF will only support referencing external data type fragments using the !include tag. Furthermore, this will only work in Async APIs defined in yaml format, as json has no way of defining tags.

As this syntax is valid within a RAML context, including data types fragments can be made at the root of the payload content, or nested within other inlined content:

Using include at root of payload
schemaFormat: application/raml+yaml;version=1.0
payload: !include external-data-type.raml
Using include within inlined content
schemaFormat: application/raml+yaml;version=1.0
payload:
type: object
properties:
id: string
user: !include external-data-type.raml
Last updated on by arielmirra