Spect (Spect v0.4.1)
Elixir typespec enhancements
Link to this section Summary
Functions
Typespec-driven object decoding
Decodes an object from a typespec, raising ArgumentError
if the type
is not found or Spect.ConvertError
for a value error during conversion.
Link to this section Functions
to_spec(data, module, name \\ :t)
Specs
Typespec-driven object decoding
This function converts a data structure into a new one derived from a type specification. This provides for the effective decoding of (nested) data structures from serialization formats that do not support Elixir's rich set of types (JSON, etc.). Atoms can be decoded from strings, tuples from lists, structs from maps, etc.
data
is the data structure to decode, module
is the name of the module
containing the type specification, and name
is the name of the @type
definition within the module (defaults to :t
).
Examples
As mentioned above, a common use case is to decode a JSON document into
an Elixir struct, for example using the Poison
parser:
"test.json"
|> File.read!()
|> Poison.Parser.parse!()
|> Spect.to_spec!(Filmography)
where the Filmography
module might contain the following structs:
defmodule Filmography do
defmodule Person do
@type t :: %__MODULE__{
name: String.t(),
birth_year: pos_integer()
}
defstruct [:name, :birth_year]
end
@type acting_credit :: %{
film: String.t(),
lead?: boolean()
}
@type t :: %__MODULE__{
subject: Person.t(),
acting_credits: [acting_credit()]
}
defstruct [:subject, acting_credits: []]
end
The conventional name for a module's primary type is t
,
so that is the default value for to_spec
's third argument. However, that
name is not mandatory, and modules can expose more than one type,
so to_spec
will accept any atom as a third argument and attempt to find a
type with that name. Continuing with the above example:
iex> data = %{"film" => "Amadeus", "lead?" => true}
%{"film" => "Amadeus", "lead?" => true}
iex> Spect.to_spec(data, Filmography, :acting_credit)
{:ok, %{film: "Amadeus", lead?: true}}
If any of the nested fields in the typespec is declared as a DateTime.t()
,
to_spec
will convert the value only if it is an
ISO 8601 string or already
a DateTime
struct.
to_spec!(data, module, name \\ :t, args \\ [])
Specs
Decodes an object from a typespec, raising ArgumentError
if the type
is not found or Spect.ConvertError
for a value error during conversion.