View Source OpenApiSpex.Schema behaviour (open_api_spex v3.21.1)
Defines the OpenApiSpex.Schema.t
type and operations for casting and validating against a schema.
The OpenApiSpex.schema
macro can be used to declare schemas with an associated struct and JSON Encoder.
Examples
defmodule MyApp.Schemas do
defmodule EmailString do
@behaviour OpenApiSpex.Schema
def schema do
%OpenApiSpex.Schema {
title: "EmailString",
type: :string,
format: :email
}
end
end
defmodule Person do
require OpenApiSpex
alias OpenApiSpex.{Reference, Schema}
OpenApiSpex.schema(%{
type: :object,
required: [:name],
properties: %{
name: %Schema{type: :string},
address: %Reference{"$ref": "#/components/schemas/Address"},
age: %Schema{type: :integer, format: :int32, minimum: 0}
}
})
end
defmodule StringDictionary do
@behaviour OpenApiSpex.Schema
def schema() do
%OpenApiSpex.Schema{
type: :object,
additionalProperties: %OpenApiSpex.Schema{
type: :string
}
}
end
end
defmodule PetCommon do
require OpenApiSpex
alias OpenApiSpex.{Schema, Discriminator}
OpenApiSpex.schema(%{
title: "PetCommon",
description: "Properties common to all Pets",
type: :object,
properties: %{
name: %Schema{type: :string},
petType: %Schema{type: :string}
},
required: [:name, :petType]
})
end
defmodule Cat do
require OpenApiSpex
alias OpenApiSpex.Schema
OpenApiSpex.schema(%{
title: "Cat",
type: :object,
description: "A representation of a cat. Note that `Cat` will be used as the discriminator value.",
allOf: [
PetCommon,
%Schema{
type: :object,
properties: %{
huntingSkill: %Schema{
type: :string,
description: "The measured skill for hunting",
default: "lazy",
enum: ["clueless", "lazy", "adventurous", "aggressive"]
}
},
required: [:huntingSkill]
}
]
})
end
defmodule Dog do
require OpenApiSpex
alias OpenApiSpex.Schema
OpenApiSpex.schema(%{
type: :object,
title: "Dog",
description: "A representation of a dog. Note that `Dog` will be used as the discriminator value.",
allOf: [
PetCommon,
%Schema {
type: :object,
properties: %{
packSize: %Schema{
type: :integer,
format: :int32,
description: "the size of the pack the dog is from",
default: 0,
minimum: 0
}
},
required: [
:packSize
]
}
]
})
end
defmodule Pet do
require OpenApiSpex
alias OpenApiSpex.Discriminator
OpenApiSpex.schema(%{
title: "Pet",
type: :object,
discriminator: %Discriminator{
propertyName: "petType"
},
oneOf: [
Cat,
Dog
]
})
end
end
Summary
Callbacks
A module implementing the OpenApiSpex.Schema
behaviour should export a schema/0
function
that produces an OpenApiSpex.Schema
struct.
Functions
Cast a simple value to the elixir type defined by a schema.
Generate example value from a %Schema{}
struct.
Generate example value from a OpenApiSpex.Schema
or a OpenApiSpex.Reference
struct.
Get the names of all properties defined for a schema.
Validate a value against a Schema.
Types
@type data_type() :: :string | :number | :integer | :boolean | :array | :object
The basic data types supported by openapi.
Global schemas lookup by name.
@type t() :: %OpenApiSpex.Schema{ additionalProperties: boolean() | t() | OpenApiSpex.Reference.t() | module() | nil, allOf: [t() | OpenApiSpex.Reference.t() | module()] | nil, anyOf: [t() | OpenApiSpex.Reference.t() | module()] | nil, default: any(), deprecated: boolean() | nil, description: String.t() | nil, discriminator: OpenApiSpex.Discriminator.t() | nil, enum: [any()] | nil, example: any(), exclusiveMaximum: boolean() | nil, exclusiveMinimum: boolean() | nil, extensions: %{required(String.t()) => any()} | nil, externalDocs: OpenApiSpex.ExternalDocumentation.t() | nil, format: String.t() | atom() | nil, items: t() | OpenApiSpex.Reference.t() | module() | nil, maxItems: integer() | nil, maxLength: integer() | nil, maxProperties: integer() | nil, maximum: number() | nil, minItems: integer() | nil, minLength: integer() | nil, minProperties: integer() | nil, minimum: number() | nil, multipleOf: number() | nil, not: t() | OpenApiSpex.Reference.t() | module() | nil, nullable: boolean() | nil, oneOf: [t() | OpenApiSpex.Reference.t() | module()] | nil, pattern: String.t() | Regex.t() | nil, properties: %{required(atom()) => t() | OpenApiSpex.Reference.t() | module()} | nil, readOnly: boolean() | nil, required: [atom()] | nil, title: String.t() | nil, type: data_type() | nil, uniqueItems: boolean() | nil, writeOnly: boolean() | nil, "x-struct": module() | nil, "x-validate": module() | nil, xml: OpenApiSpex.Xml.t() | nil }
The Schema Object allows the definition of input and output data types. These types can be objects, but also primitives and arrays. This object is an extended subset of the JSON Schema Specification Wright Draft 00.
Example
alias OpenApiSpex.Schema
%Schema{
title: "User",
type: :object,
properties: %{
id: %Schema{type: :integer, minimum: 1},
name: %Schema{type: :string, pattern: "[a-zA-Z][a-zA-Z0-9_]+"},
email: %Schema{type: :string, format: :email},
last_login: %Schema{type: :string, format: :"date-time"}
},
required: [:name, :email],
example: %{
"name" => "joe",
"email" => "joe@gmail.com"
}
}
Callbacks
@callback schema() :: t()
A module implementing the OpenApiSpex.Schema
behaviour should export a schema/0
function
that produces an OpenApiSpex.Schema
struct.
Functions
Cast a simple value to the elixir type defined by a schema.
By default, object types are cast to maps, however if the "x-struct" attribute is set in the schema, the result will be constructed as an instance of the given struct type.
Examples
iex> OpenApiSpex.Schema.cast(%Schema{type: :integer}, "123", %{})
{:ok, 123}
iex> {:ok, dt = %DateTime{}} = OpenApiSpex.Schema.cast(%Schema{type: :string, format: :"date-time"}, "2018-04-02T13:44:55Z", %{})
...> dt |> DateTime.to_iso8601()
"2018-04-02T13:44:55Z"
Casting Polymorphic Schemas
Schemas using discriminator
, allOf
, oneOf
, anyOf
are cast using the following rules:
If a
discriminator
is present, cast the properties defined in the base schema, then cast the result using the schema identified by the discriminator. To avoid infinite recursion, the discriminator is only dereferenced if the discriminator property has not already been cast.Cast the properties using each schema listing in
allOf
. When a property is defined in multipleallOf
schemas, it will be cast using the first schema listed containing the property.Cast the value using each schema listed in
oneOf
, stopping as soon as a successful cast is made.Cast the value using each schema listed in
anyOf
, stopping as soon as a successful cast is made.
@spec example(schema :: t() | module() | OpenApiSpex.Reference.t()) :: map() | String.t() | number() | boolean()
Generate example value from a %Schema{}
struct.
This is useful as a simple way to generate values for tests.
Example:
test "create user", %{conn: conn} do
user_request_schema = MyAppWeb.Schemas.UserRequest.schema()
req_body = OpenApiSpex.Schema.example(user_request_schema)
resp_body =
conn
|> post("/users", req_body)
|> json_response(201)
assert ...
end
@spec example(schema :: t() | module(), schemas :: OpenApiSpex.OpenApi.t() | map()) :: map() | String.t() | number() | boolean()
Generate example value from a OpenApiSpex.Schema
or a OpenApiSpex.Reference
struct.
The second parameter must either be an OpenApiSpex.OpenApi
struct or a map of schemas.
See also: example/1
.
Get the names of all properties defined for a schema.
Includes all properties directly defined in the schema, and all schemas
included in the allOf
list.
@spec validate(t() | OpenApiSpex.Reference.t(), any(), %{ required(String.t()) => t() | OpenApiSpex.Reference.t() }) :: :ok | {:error, String.t()}
Validate a value against a Schema.
This expects that the value has already been cast
to the appropriate data type.
Examples
iex> OpenApiSpex.Schema.validate(%OpenApiSpex.Schema{type: :integer, minimum: 5}, 3, %{})
{:error, "#: 3 is smaller than minimum 5"}
iex> OpenApiSpex.Schema.validate(%OpenApiSpex.Schema{type: :string, pattern: "(.*)@(.*)"}, "joe@gmail.com", %{})
:ok
iex> OpenApiSpex.Schema.validate(%OpenApiSpex.Schema{type: :string, pattern: "(.*)@(.*)"}, "joegmail.com", %{})
{:error, "#: Value \"joegmail.com\" does not match pattern: (.*)@(.*)"}