OpenAPI support
Schemas and types
Primitives
Stainless supports these primitives from the OpenAPI specification:
string
null
boolean
integer
number
TypeScript
export interface Data {
strings: string;
nulls: null;
booleans: boolean;
integers: number;
numbers: number;
}
Python
class Data(BaseModel):
strings: str
nulls: None
booleans: bool
integers: int
numbers: float
Go
type Data struct {
String string
Nulls interface{}
Booleans bool
Integers int64
Numbers float64
}
object
Stainless supports multiple variations of object
types.
# MapTypedValues
type: object
properties:
foo:
type: string
description: A foo property
bar:
type: boolean
required: [foo]
TypeScript
interface FooObject {
// A foo field
foo: string:
bar?: boolean;
}
Python
class FooObject(BaseModel):
# A foo field
foo: str
bar: Optional[bool]
Go
type FooObject struct {
// A foo field
Foo string `json:"foo,required"`
Bar bool `json:"bar"`
}
oneOf
and anyOf
Stainless treats both oneOf
and anyOf
as equivalent to a TypeScript union.
oneOf:
- type: object
properties:
foo:
type: string
required: [foo]
- type: object
properties:
bar:
type: boolean
required: [bar]
JSON Schema states that a oneOf
schema must match exactly one of the given schemas. This means that a schema like
oneOf:
- type: string
- enum: ['CLOSED', 'OPEN']
has the surprising behavior that CLOSED
is not accepted by the schema since it matches both of the
schemas in the oneOf
, not one. Counterintuitively this schema accepts all strings except CLOSED
and
OPEN
.
TypeScript
export interface FooObj {
foo: string;
}
export interface BarObj {
bar: boolean;
}
export type Schema = FooObj | BarObj;
Python
class FooObj(BaseModel):
foo: str
class BarObj(BaseModel):
bar: bool
Schema = Union[FooObj, BarObj]
Go
type FooObj struct {
Foo string `json:"foo"`
}
func (*FooObj) implementsSchema() {}
type BarObj struct {
Bar bool `json:"bar"`
}
func (*BarObj) implementsSchema() {}
type Schema interface {
implementsSchema()
}
discriminator
A discriminator
property for a union schema allows mapping a JSON object to one of the variants by looking up a
single property. This simplifies deserialization and makes mapping much faster. We recommend that all unions
which have multiple object variants specify this in the schema.
oneOf:
- type: object
properties:
kind:
const: 'foo_object'
foo:
type: string
required: [foo]
- type: object
properties:
kind:
const: 'bar_object'
bar:
type: boolean
required: [bar]
discriminator:
propertyName: kind
allOf
By default, Stainless handles allOf
by flattening the entries into one schema and treating it like an object
.
However, if one of the entries is a model, then Stainless uses the model entry as a part of composition.
# ObjectIntersection
allOf:
- $ref: '#/components/schemas/FooObject'
- type: object
properties:
baz:
type: string
- type: object
properties:
haz:
type: boolean
TypeScript
export interface ObjectIntersection extends FooObject {
baz?: string;
haz?: boolean;
}
Python
class ObjectIntersection(BaseModel, FooObject):
# A foo
baz: Optional[str]
has: Optional[bool]
Go
type ObjectIntersection struct {
FooObject
Baz string `json:"baz"`
Has bool `json:"has"`
}
date
and date-time
Stainless supports generating rich, language specific types for date and datetime schemas.
# DateObj
type: string
format: date
# DateTimeObj
type: string
format: date-time
TypeScript
// Not fully supported yet
export type DateObj = string;
export type DateTimeObj = string;
Python
import datetime
DateObj = datetime.date
DateTimeObj = datetime.datetime
Go
import "time"
type Data struct {
DateObj param.Field[time.Time] `format:"date"`
DateTimeObj param.Field[time.Time] `format:"date-time"`
}
additionalProperties
Stainless supports OpenAPI's additionalProperties
specification which is equivalent to TypeScript's Record
type or Python's dict
type.
# MapTypedValues
type: object
additionalProperties:
type: integer
# MapUntypedValues
type: object
additionalProperties: true
TypeScript
export type MapTypedValues = Record<string, number>;
export type MapUntypedValues = Record<string, unknown>;
Python
MapTypedValues = Dict[str, int]
MapUntypedValues = Dict[str, object]
Go
type Data struct {
MapTypedValues map[string]int64
MapUntypedValues map[string]interface{}
}
propertyNames
Stainless does not support propertyNames
, which is used to define the schema of the map key.
type: object
propertyNames:
type: string
enum: ["name", "email"]
enum
and const
Enums define a set of number and string literals that could be specified withing a field.
# FooModel
type: string
enum: [bar, baz, bam]
TypeScript
export type FooModel = 'bar' | 'baz' | 'bam'
Python
FooModel = Literal['bar' | 'baz' | 'bam']
Go
type FooModel string
const (
FooModelBar FooModel = 'bar'
FooModelBaz = 'baz'
FooModelBam = 'bam'
)
x-enum-descriptions
Stainless optionally supports providing enum member descriptions, which either get rendered in the member variables or the main enum type, depending on the language.
Descriptions can be provided with either the
x-enum-descriptions
extension or with a oneOf
:
# FooModel
oneOf:
- const: 'bar'
description: 'A bar variant'
- const: 'baz'
description: 'A baz variant'
- const: 'bam'
description: 'A bam variant'
Unknown and Any
Stainless supports specifying types that are unknown
and any
, and accepts any valid JSON value. The JSON
Schema way of specifying this behavior is to specify an 'empty' schema, but this often happens by accident.
Unless you add an x-stainless-any
, Stainless adds a diagnostic note to your OpenAPI schema.
# EmptySchema (the OpenAPI default)
type: 'object'
properties:
foo:
x-stainless-any: true
TypeScript
export type EmptySchema = {
foo: unknown;
};
Python
class EmptySchema(BaseModel):
foo: object
Go
type EmptySchema struct {
Foo interface{} `json:'foo'`
}