open_api_spex v3.4.0 OpenApiSpex.Schema behaviour View Source

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: %{
          type: :string
        }
      }
    end
  end

  defmodule Pet do
    require OpenApiSpex
    alias OpenApiSpex.{Schema, Discriminator}

    OpenApiSpex.schema(%{
      title: "Pet",
      type: :object,
      discriminator: %Discriminator{
        propertyName: "petType"
      },
      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: [
        Pet,
        %Schema{
          type: :object,
          properties: %{
            huntingSkill: %Schema{
              type: :string,
              description: "The measured skill for hunting",
              default: "lazy",
              enum: ["clueless", "lazy", "adventurous", "aggresive"]
            }
          },
          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: [
        Pet,
        %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
end

Link to this section Summary

Types

The basic data types supported by openapi

Global schemas lookup by name

Functions

Cast a simple value to the elixir type defined by a schema

Get the names of all properties definied for a schema

Validate a value against a Schema

Callbacks

A module implementing the OpenApiSpex.Schema behaviour should export a schema/0 function that produces an OpenApiSpex.Schema struct

Link to this section Types

Link to this type

data_type() View Source
data_type() :: :string | :number | :integer | :boolean | :array | :object

The basic data types supported by openapi.

Reference

Link to this type

schemas() View Source
schemas() :: %{optional(String.t()) => t()}

Global schemas lookup by name.

Link to this type

t() View Source
t() :: %OpenApiSpex.Schema{
  allOf: [OpenApiSpex.Schema.t() | OpenApiSpex.Reference.t() | module()] | nil,
  xml: OpenApiSpex.Xml.t() | nil,
  additionalProperties:
    boolean()
    | OpenApiSpex.Schema.t()
    | OpenApiSpex.Reference.t()
    | module()
    | nil,
  deprecated: boolean() | nil,
  exclusiveMaximum: boolean() | nil,
  multipleOf: number() | nil,
  "x-struct": module() | nil,
  example: any(),
  minProperties: integer() | nil,
  description: String.t() | nil,
  required: [atom()] | nil,
  format: String.t() | atom() | nil,
  oneOf: [OpenApiSpex.Schema.t() | OpenApiSpex.Reference.t() | module()] | nil,
  uniqueItems: boolean() | nil,
  maxProperties: integer() | nil,
  type: data_type() | nil,
  title: String.t() | nil,
  pattern: String.t() | Regex.t() | nil,
  enum: [String.t()] | nil,
  externalDocs: OpenApiSpex.ExternalDocumentation.t() | nil,
  maximum: number() | nil,
  exclusiveMinimum: boolean() | nil,
  discriminator: OpenApiSpex.Discriminator.t() | nil,
  not: OpenApiSpex.Schema.t() | OpenApiSpex.Reference.t() | module() | nil,
  writeOnly: boolean() | nil,
  maxLength: integer() | nil,
  minLength: integer() | nil,
  maxItems: integer() | nil,
  minItems: integer() | nil,
  items: OpenApiSpex.Schema.t() | OpenApiSpex.Reference.t() | module() | nil,
  nullable: boolean() | nil,
  readOnly: boolean() | nil,
  anyOf: [OpenApiSpex.Schema.t() | OpenApiSpex.Reference.t() | module()] | nil,
  properties:
    %{
      optional(atom()) =>
        OpenApiSpex.Schema.t() | OpenApiSpex.Reference.t() | module()
    }
    | nil,
  minimum: number() | nil,
  default: any()
}

Schema Object

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: %Scheam{type: :string, format: :email},
    last_login: %Schema{type: :string, format: :"date-time"}
  },
  required: [:name, :email],
  example: %{
    "name" => "joe",
    "email" => "joe@gmail.com"
  }
}

Link to this section Functions

Link to this function

cast(schema, value, schemas) View Source

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 multiple allOf 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 sucessful cast is made.

  • Cast the value using each schema listed in anyOf, stopping as soon as a succesful cast is made.

Get the names of all properties definied for a schema.

Includes all properties directly defined in the schema, and all schemas included in the allOf list.

Link to this function

validate(schema, val, schemas) View Source
validate(OpenApiSpex.Schema.t() | OpenApiSpex.Reference.t(), any(), %{
  optional(String.t()) => OpenApiSpex.Schema.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: (.*)@(.*)"}
Link to this function

validate(ref, val, path, schemas) View Source
validate(
  OpenApiSpex.Schema.t() | OpenApiSpex.Reference.t(),
  any(),
  String.t(),
  %{optional(String.t()) => OpenApiSpex.Schema.t() | OpenApiSpex.Reference.t()}
) :: :ok | {:error, String.t()}

Link to this section Callbacks

A module implementing the OpenApiSpex.Schema behaviour should export a schema/0 function that produces an OpenApiSpex.Schema struct.