Types

Type naming

Speakeasy tries to name your types using the shortest name possible, this is done by trying to deduce a name from its surrounding context.

Types defined via components will generally fare best when it comes to the name chosen for them. Where possible, we use the component's key name as the type name.

For example given the following schema:


components:
schemas:
User:
type: object
properties:
id:
type: string
name:
type: string

The type name for the User schema will be User where possible unless it potentially conflicts with another type in the same namespace then name resolution will kick in and the earliest encountered type will be named User and the later encountered types will have various context used to determine relevant prefixes/suffixes to add to the types to avoid conflicts.

Where a component name is unavailable for example when the type is defined inline in a schema, request, response, parameter etc

We will start using other context to determine the name of the type in the following order:

  • x-speakeasy-name-override extension value in the schema
  • title property in the schema
  • $anchor property in the schema
  • any other surrounding context of the schema

The types that are named this way are objects that become classes, integer and string types that have enum values defined in the schema or oneOf/anyOf schemas that become union types.

Inline schemas like in the below example will generally run the risk of having names chosen that will conflict with other types more often and will generally start having context prefixes/suffixes added to the type names until the type no longer conflicts with another type.


paths:
/users:
get:
operationId: getUsers
responses:
'200':
content:
application/json:
schema:
type: array
items:
type: object # inline schema that will be named based on surrounding context
title: User
properties:
id:
type: string
name:
type: string
/user:
get:
operationId: getUser
responses:
'200':
content:
application/json:
schema:
type: object # inline scheme that will be named based on surrounding context
title: User
properties:
id:
type: string
name:
type: string

In the above example both inline schemas will attempt to be named User but will conflict with one another (we don't do any inference to try and understand if these are the same type) the second schema will have a context prefix added to it to avoid a conflict with the first schema.

Some of the context prefixes/suffixes that can be added to the type names are:

  • Reference Type
  • Reference Name
  • Property Name
  • Operation Name
  • Tag Name
  • Request
  • Response
  • Position in oneOf/anyOf schema
  • etc

When we run out of context to name the type we will start using numbers to suffix the type name.

To avoid unexpected type names and ensure you get the names you expect the recommendation is to use unique component names for your schemas whereever possible.

Input/Output Models

Speakeasy will generate separate input and output models for schemas that are used in both request and response bodies and define readOnly and writeOnly flags on their properties.

For example given the following schema:


paths:
/drinks/{id}:
post:
operationId: updateDrink
parameters:
- name: id
in: path
required: true
schema:
type: string
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/Drink'
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/Drink'
components:
schemas:
Drink:
type: object
properties:
id:
type: string
readOnly: true
stockUpdate:
type: integer
writeOnly: true
name:
type: string
category:
type: string
stock:
type: integer
readOnly: true

The Drink component is used both as a request body and response body schema, but it is using fields that can only be set when updating the drink and read when getting the returned drink.

In this case Speakeasy will generate two models DrinkInput and DrinkOutput._createMdxContent

DrinkInput will have the following properties:

  • stockUpdate
  • name
  • category

DrinkOutput will have the following properties:

  • id
  • name
  • category
  • stock

In the case where a schema has only readOnly flags and no writeOnly flags or vice versa, Speakeasy will generate two models still if used in both request and response bodies, but the Input/Output schema will be added only to the relevant models based on the flags.

The Input/Output suffixes can be reconfigured using the inputModelSuffix and outputModelSuffix options in the gen.yaml file. See the gen.yaml reference for more infomation.

Const / Default Handling

If a schema has a const or default value defined on it, Speakeasy will generate code to handle these where ever possible.

Const

Consts allow you to specify a value that must be transmitted to the server and is always expected to be received from the server.

For example:


components:
schemas:
Drink:
type: object
properties:
type:
type: string
const: 'drink'

The type property has a const value of drink the SDK will be generated with this field not being available to set as the value drink will always be transmitted. Then const getters will be generated for accessing the value if required.

Default

Defaults allow you to specify a value to be transmitted to the server if none is provided by the end user.

For example:


components:
schemas:
Drink:
type: object
properties:
category:
type: string
default: 'spirits'
required:
- category

The category property has a default of spirits even though this field is marked required the SDK will be generated with this field being optional and the value spirits will be transmitted if no other value is provided by the end user.

Examples

If an example or examples field is provided on the type, Speakeasy will use the values (if valid for the defined schema) to populate usage snippets in the generated SDKs.

If more than one example is provided in the examples field, then a random example will be chosen.