Exonerate supports JSONSchema format validation through the :format option. This guide details all available format filters and how to configure them.

Basic Usage

To enable format validation, pass the :format option to any Exonerate macro:

Exonerate.function_from_string(:def, :validate, """
  {"type": "string", "format": "email"}
""", format: true)

Configuration

The :format option accepts either true or a keyword list:

  • true: shorthand for [default: true]

  • keywords:

    • :at: a list of {<json pointer>, <filter-spec>} tuples to apply format filters in specific locations in the schema. This can be used to specify custom filters for non-default format types. It can also be used to override default formatting. <json pointer> should be a string which may be relative if no "id" or "$id" metadata are present in the parents of the location. Otherwise, the pointer must the a uri of the nearest parent containing "id" or "$id" metadata, with the relative pointer applied as the fragment of the uri.

      <filter-spec> may either be a module, which implies the existence of the module.validate/1 function, {module, function} which implies the existence of module.function/1, or {module, function, [extra-args]} which implies the existence of module.function/n where the extra args are appended to the end of string to be validated.

      In all cases, the validation function is expected to emit :ok if the string validates, or {:error, reason}, if it does not. reason should either be a string or nil.

    • :type: a list of {<format-type>, <filter-spec>} to apply across the schema whenever <format-type> is encountered. This can be used to specify custom filters for non-default format types. It can also be used to override default formatting. <filter-spec> is as above.

    • :default: true to enable all default filters or a list of strings specifying the default format types to enable.

Available Format Types

Date and Time

"date-time"

Enables the default date-time filter for all {"format": "date-time"} contexts. This uses Elixir's NaiveDateTime.from_iso8601/1 parser.

"date-time-utc"

Enables the default date-time-utc filter for all {"format": "date-time-utc"} contexts. This uses Elixir's DateTime.from_iso8601/1 parser, and requires the offset to be 0 from UTC.

"date-time-tz"

Enables the default date-time filter for all {"format": "date-time-tz"} context strings. This uses Elixir's DateTime.from_iso8601/1 parser, which requires an offset to be specified.

"date"

Enables the default date filter for all {"format": "date"} context strings. This uses Elixir's Date.from_iso8601/1 parser.

"time"

Enables the default time filter for all {"format": "time"} context strings. This uses Elixir's Time.from_iso8601/1 parser.

"duration"

Enables the default duration filter for all {"format": "duration"} context strings. This uses a custom ABNF validator that matches Appendix A of RFC 3339: https://www.rfc-editor.org/rfc/rfc3339.txt

The validation function can be generated by Exonerate.Formats.Duration. Requires NimbleParsec and Pegasus dependencies.

Network

"ipv4"

Enables the default ipv4 filter for all {"format": "ipv4"} context strings. This uses Erlang's :inet.parse_ipv4strict_address/1 parser.

"ipv6"

Enables the default ipv6 filter for all {"format": "ipv6"} context strings. This uses Erlang's :inet.parse_ipv6strict_address/1 parser.

"email"

Enables the default email filter for all {"format": "email"} context strings. This uses a custom ABNF validator that matches section 4.1.2 of RFC 5322: https://www.rfc-editor.org/rfc/rfc5322.txt

The validation function can be generated by Exonerate.Formats.Email. Requires NimbleParsec and Pegasus dependencies.

"idn-email"

Enables the default idn-email (i18n email address) filter for all {"format": "idn-email"} context strings. This uses a custom ABNF validator that matches section 3.3 of RFC 6531: https://www.rfc-editor.org/rfc/rfc5322.txt

The validation function can be generated by Exonerate.Formats.IdnEmail. Requires NimbleParsec and Pegasus dependencies.

"hostname"

Enables the default hostname filter for all {"format": "hostname"} context strings. This uses a custom ABNF validator that matches section 2.1 of RFC 1123: https://www.rfc-editor.org/rfc/rfc1123.txt

The validation function can be generated by Exonerate.Formats.Hostname. Requires NimbleParsec and Pegasus dependencies.

"idn-hostname"

Enables the default idn-hostname (i18n hostname) filter for all {"format": "idn-hostname"} context strings.

Note that in order to use this filter, you must add the :idna library to your dependencies.

The validation function can be generated by Exonerate.Formats.IdnHostname. Requires NimbleParsec and Pegasus dependencies.

URIs and IRIs

"uri"

Enables the default uri filter for all {"format": "uri"} context strings. This uses a custom ABNF validator that matches section 3 of RFC 3986: https://www.rfc-editor.org/rfc/rfc3986.txt.

Absolute URIs

URIs must be absolute, i.e. they must contain a scheme, host, and path. If you need relative URIs, use the uri-reference filter.

The validation function can be generated by Exonerate.Formats.Uri. Requires NimbleParsec and Pegasus dependencies.

"uri-reference"

Enables the default uri-reference filter for all {"format": "uri-reference"} context strings. This uses a custom ABNF validator that matches section 3 of RFC 3986: https://www.rfc-editor.org/rfc/rfc3986.txt.

The validation function can be generated by Exonerate.Formats.UriReference. Requires NimbleParsec and Pegasus dependencies.

"iri"

Enables the default iri (i18n uri) filter for all {"format": "iri"} context strings. This uses a custom ABNF validator that matches section 2.2 of RFC 3987: https://www.rfc-editor.org/rfc/rfc3987.txt.

Absolute IRIs

IRIs must be absolute, i.e. they must contain a scheme, host, and path. If you need relative IRIs, use the iri-reference filter.

The validation function can be generated by Exonerate.Formats.Iri. Requires NimbleParsec and Pegasus dependencies.

"iri-reference"

Enables the default iri-reference (i18n uri) for all {"format": "iri-reference"} context strings. This uses a custom ABNF validator that matches section 2.2 of RFC 3987: https://www.rfc-editor.org/rfc/rfc3987.txt.

The validation function can be generated by Exonerate.Formats.IriReference. Requires NimbleParsec and Pegasus dependencies.

"uri-template"

Enables the default uri-template filter for all {"format": "uri-template"} context strings. This uses a custom ABNF validator that matches section 2.3 of RFC 6570: https://www.rfc-editor.org/rfc/rfc6570.txt.

URI-Template parent

uri-templates are templated against iri-reference strings. This means they do not need to be absolute, and they may include unicode characters.

The validation function can be generated by Exonerate.Formats.UriTemplate. Requires NimbleParsec and Pegasus dependencies.

JSON Pointers

"json-pointer"

Enables the default json-pointer filter for all {"format": "json-pointer"} context strings. This uses a custom ABNF validator that matches section 3 of RFC 6901: https://www.rfc-editor.org/rfc/rfc6901.txt

The validation function can be generated by Exonerate.Formats.JsonPointer. Requires NimbleParsec and Pegasus dependencies.

"relative-json-pointer"

Enables the default relative-json-pointer filter for all {"format": "relative-json-pointer"} context strings. This uses a custom ABNF validator that matches the following RFC proposal: https://datatracker.ietf.org/doc/html/draft-handrews-relative-json-pointer-01

The validation function can be generated by Exonerate.Formats.RelativeJsonPointer. Requires NimbleParsec and Pegasus dependencies.

Other

"uuid"

Enables the default uuid filter for all {"format": "uuid"} context strings.

"regex"

Enables the default regex filter for all {"format": "regex"} context strings. Note: this does not compile the regex, instead it uses a custom ABNF validator that matches the ECMA-262 standard: https://www.ecma-international.org/publications-and-standards/standards/ecma-262/

The validation function can be generated by Exonerate.Formats.Regex. Requires NimbleParsec and Pegasus dependencies.

Custom Format Filters

You can define custom format filters by implementing a validation function that:

  1. Accepts a string as its first argument
  2. Returns :ok if the string validates
  3. Returns {:error, reason} if validation fails, where reason is a string or nil

Example

defmodule MyApp.Formats.PhoneNumber do
  def validate(string) do
    if Regex.match?(~r/^\+?[1-9]\d{1,14}$/, string) do
      :ok
    else
      {:error, "invalid phone number format"}
    end
  end
end

# Use with :type option (applies globally)
Exonerate.function_from_string(:def, :validate, """
  {"type": "string", "format": "phone"}
""", format: [type: [{"phone", MyApp.Formats.PhoneNumber}]])

# Use with :at option (applies at specific location)
Exonerate.function_from_string(:def, :validate, """
  {"type": "object", "properties": {"phone": {"type": "string", "format": "phone"}}}
""", format: [at: [{"/properties/phone", MyApp.Formats.PhoneNumber}]])