Explicit, opt-in data transformations.
Encoders never drop, stringify, or replace values on their own. When a value
cannot be represented in a target format, call one of these functions (or pass
them to Formata.convert/4 with :transforms) to make the loss explicit.
Every transformation returns {:ok, data} or {:error, [%Formata.Error{kind: :transform}]}.
iex> Formata.Transform.drop_nils(%{"a" => 1, "b" => nil})
{:ok, %{"a" => 1}}
iex> Formata.Transform.temporal_to_iso8601(%{"on" => ~D[2024-05-01]})
{:ok, %{"on" => "2024-05-01"}}
Summary
Functions
Applies a list of transformations in order, stopping at the first error.
Removes map entries whose value is nil, recursively. nil list elements
are kept, because removing them would shift positions.
Replaces every nil (map values and list elements) with value.
Converts :infinity, :negative_infinity, and :nan to the strings
"inf", "-inf", and "nan", recursively.
Converts atom, integer, float, and boolean map keys to strings, recursively.
Converts Date, Time, NaiveDateTime, and DateTime values to ISO 8601
strings, recursively.
Types
@type transform() :: :drop_nils | :temporal_to_iso8601 | :stringify_keys | :special_floats_to_strings | {:replace_nils, term()} | (term() -> {:ok, term()} | {:error, [Formata.Error.t(), ...]})
Functions
@spec apply_all(term(), [transform()]) :: {:ok, term()} | {:error, [Formata.Error.t(), ...]}
Applies a list of transformations in order, stopping at the first error.
Each element is a transformation name (:drop_nils, :temporal_to_iso8601,
:stringify_keys, :special_floats_to_strings), {:replace_nils, value},
or a one-argument function returning {:ok, data} | {:error, errors}.
iex> Formata.Transform.apply_all(%{"a" => nil, "t" => ~T[10:00:00]}, [:drop_nils, :temporal_to_iso8601])
{:ok, %{"t" => "10:00:00"}}
Removes map entries whose value is nil, recursively. nil list elements
are kept, because removing them would shift positions.
iex> Formata.Transform.drop_nils(%{"a" => %{"b" => nil, "c" => [nil, 1]}})
{:ok, %{"a" => %{"c" => [nil, 1]}}}
Replaces every nil (map values and list elements) with value.
iex> Formata.Transform.replace_nils(%{"a" => nil, "b" => [nil]}, "")
{:ok, %{"a" => "", "b" => [""]}}
Converts :infinity, :negative_infinity, and :nan to the strings
"inf", "-inf", and "nan", recursively.
iex> Formata.Transform.special_floats_to_strings(%{"x" => :infinity})
{:ok, %{"x" => "inf"}}
@spec stringify_keys(term()) :: {:ok, term()} | {:error, [Formata.Error.t(), ...]}
Converts atom, integer, float, and boolean map keys to strings, recursively.
Fails with :key_collision if two keys of one map would become the same
string (for example :a and "a"), and with :invalid_key for keys that have
no string form (nil, tuples, lists, maps, ...).
iex> Formata.Transform.stringify_keys(%{name: "Ada", tags: %{1 => true}})
{:ok, %{"name" => "Ada", "tags" => %{"1" => true}}}
iex> {:error, [%Formata.Error{code: :key_collision}]} =
...> Formata.Transform.stringify_keys(%{:a => 1, "a" => 2})
Converts Date, Time, NaiveDateTime, and DateTime values to ISO 8601
strings, recursively.
iex> Formata.Transform.temporal_to_iso8601([~U[2024-01-02 03:04:05Z]])
{:ok, ["2024-01-02T03:04:05Z"]}