This page describes the input accepted by parse/1 and parse/2, type conversion, validation, and returned errors. See the DSL reference for types and field options.

日本語版

Input keys

Each field's input key is specified by source:. It accepts a string or atom and can be used in both field/3 within a defschema block and map definitions.

Input values are resolved in this order:

  1. The key specified by source:, or the field name as a string when it is omitted
  2. The field name as an atom declared by the schema

When both keys exist in the input map, the string key or the key specified by source: takes precedence.

Input fields not present in the schema are ignored by default. This accepts auxiliary parameters added by frameworks such as LiveView or HTTP request handling, and unknown values are not retained in the output struct.

defschema strict: true do ... end or compile!/2 with strict: true rejects an unknown top-level key as {:unknown_param, key}. use ExParamsSchema, strict: true sets a module default. strict: true on a nested map applies only to that map; an unknown key returns the nearest error: (or the parent field's default error). A strict object is also emitted as JSON Schema with "additionalProperties": false.

Absent values, empty strings, and defaults

When a field is absent, it is processed in this order:

  1. Use default: when present.
  2. Use nil when optional: true.
  3. Otherwise return the field's error.

An explicitly supplied nil or empty string for an optional: true field becomes nil. For a :string field, a whitespace-only string also becomes nil. In these cases the default is not applied. A default is applied only when the field itself is absent.

Defaults are converted and validated when the schema is defined. A params module with an invalid default cannot compile. The normalized default is used both by parse/1 and defstruct.

nullable

nullable: true accepts nil when the field is present. It is distinct from optional: true, which allows the field to be absent.

Type conversion and validation

Input is converted to its declared type and then validated against the generated JSON Schema.

Input-key resolution
  → absent-value and empty-string processing
  → type conversion
  → JSON Schema validation
  → struct construction

:string trims leading and trailing whitespace during conversion, and constraints such as min_length: apply to the trimmed string. Other built-in types do not trim input strings: :integer, :float, :number, and :boolean reject values such as " 12 " and "true ". Whitespace handling for custom types is decided by the adapter's cast/2.

:date converts ISO 8601 date strings to Date. :datetime accepts ISO 8601 datetimes that include a time zone and normalizes them to UTC DateTime values. Datetimes without a time zone are rejected. Both types also accept Date / DateTime values directly, and apply the same conversion rules to default:.

Schema definition errors

The following problems are reported as ArgumentError when a schema is defined, rather than while parsing params:

  • Unknown or duplicate options
  • Duplicate field names at the same nesting level
  • Unsupported types
  • Constraints that do not apply to the type, such as minimum: on a string
  • Invalid option value types
  • Reversed bounds such as minimum and maximum
  • An empty atom enum or an enum containing non-atoms
  • Field-only options such as optional: on a list item
  • A default that cannot be converted to its declared type or does not satisfy constraints
  • enum: or in: members incompatible with the converted field value's type

in: accepts only lists, ranges, and MapSets that can be determined to be finite at compile time. Arbitrary Enumerables and streams are not accepted.

enum: and in: members are compared with the converted value by JSON Schema, so they must have the target type. :any permits any non-nil value; nil is allowed only by nullable: true or :null. Atom enums cannot be combined with enum: or in:.

Errors

When casting or validation fails, the field's error: is returned. When omitted, it is {:invalid_param, field_name}.

Nested values use the nearest error:. For multiple JSON Schema errors, fields declared in a keyword list are handled in declaration order. Ordering among nested fields declared in a map is not guaranteed.

Detailed errors

parse_detailed/1 and parse_detailed/2 return the same successful value as ordinary parse; on failure, they return a list of ExParamsSchema.ValidationError. Each error has path (string map keys and integer list indices), keyword, reason, and details. reason is the same value returned by ordinary parse through error:.

Every JSON Schema violation is returned when there are multiple violations. Missing required values, type-conversion errors, and strict-mode unknown keys are detected during conversion, so only the first error is returned. Their keyword is :cast or :additional_properties, respectively.