Setting up structures
use Estructura or use Estructura.Nested
Basic structure definition
defmodule MyStruct do
use Estructura
defstruct [:field1, :field2]
endNested structure definition with types and validation
defmodule User do
use Estructura.Nested
defstruct [
name: "",
address: %{city: "", postal_code: ""}
]
def type(:name), do: Estructura.Nested.Type.String
def validate(:name, value), do: String.length(value) > 0
enduse Estructura.WIA
With Indifferent Access (atom and binary keys)
defmodule Config do
use Estructura.WIA,
fields: [
host: [default: "localhost"],
port: [default: 4000, coerce: true, validate: true]
]
@impl Config.Coercible
def coerce_port(value) when is_integer(value), do: {:ok, value}
def coerce_port(value) when is_binary(value) do
case Integer.parse(value) do
{int, ""} -> {:ok, int}
_ -> {:error, "invalid port"}
end
end
@impl Config.Validatable
def validate_port(port) when port in 1..65535, do: {:ok, port}
def validate_port(_port), do: {:error, "port out of range"}
end
# Access with both atom and binary keys
config = %Config{}
config[:port] #=> 4000
config["port"] #=> 4000
put_in(config, ["port"], "8080") #=> %Config{host: "localhost", port: 8080}Type System
Built-in Types
Available types for common data structures
Estructura.Nested.Type.DateTime
Estructura.Nested.Type.Date
Estructura.Nested.Type.Time
Estructura.Nested.Type.URI
Estructura.Nested.Type.IP
Estructura.Nested.Type.String
Estructura.Nested.Type.UUIDType Scaffolds
Enum Types for predefined values
defmodule Status do
use Estructura.Nested.Type.Enum,
elements: [:pending, :active, :completed]
endTag Sets for multiple predefined values
defmodule Categories do
use Estructura.Nested.Type.Tags,
elements: [:tech, :art, :science]
endValidation and Coercion
validate/2
Define validation rules for fields
def validate(:age, value), do: value >= 0
def validate("address.postal_code", value), do: String.match?(value, ~r/^\d{5}$/)coerce/2
Define coercion rules for data transformation
def coerce(:temperature, str) when is_binary(str) do
case Float.parse(str) do
{num, ""} -> {:ok, num}
_ -> {:error, "Invalid number"}
end
endSpecial Features
Lazy Values
Defer computation until needed
defmodule Cache do
use Estructura.Nested
defstruct value: Estructura.Lazy.new(&expensive_computation/1)
endFlattening
Convert nested structures to flat maps
# Enable flattening
use Estructura.Nested, flattenable: true
# Usage
Estructura.Flattenable.flatten(struct)
# => %{"name" => "value", "address_city" => "London"}Property Testing
Generate test data automatically
property "valid structures are validated" do
check all struct <- MyStruct.__generator__() do
assert {:ok, ^struct} = MyStruct.validate(struct)
end
endCommon Options
flattenable: true- Enable structure flatteningjason: true- Enable JSON encodingtransformer: true- Enable transformation capabilitiesindifferent: true- Enable indifferent access (atom and binary keys)