Estructura.WIA (With Indifferent Access) provides a struct-like container
that can be accessed by both atom and binary keys, replicating
Ruby's Hash#with_indifferent_access pattern.
Internally, keys are always stored as atoms. Both atom and binary keys
are accepted in Access operations and normalized to atoms transparently.
This module builds on top of Estructura, reusing its Access implementation,
coercion, validation, and Enumerable protocol. It adds indifferent key
normalization, and implements Inspect, Collectable, and optionally
Jason.Encoder protocols to mimic map behaviour.
Usage
defmodule MyWIA do
use Estructura.WIA,
fields: [
foo: [default: 42],
bar: [default: ""],
baz: [default: %{}]
]
@impl MyWIA.Coercible
def coerce_foo(value) when is_integer(value), do: {:ok, value}
def coerce_foo(value) when is_binary(value) do
case Integer.parse(value) do
{int, ""} -> {:ok, int}
_ -> {:error, "not a valid integer"}
end
end
@impl MyWIA.Validatable
def validate_foo(value) when value >= 0, do: {:ok, value}
def validate_foo(_), do: {:error, ":foo must be non-negative"}
endThen both atom and binary keys work interchangeably:
wia = %MyWIA{}
wia[:foo] #=> 42
wia["foo"] #=> 42
put_in(wia, ["foo"], 100) #=> %MyWIA{foo: 100, ...}Options
fields— a keyword list of{field_name, opts}whereoptsis a keyword list with::default— the default value for the field (default:nil):coerce— whether to generate a coercion callback for this field (default:false):validate— whether to generate a validation callback for this field (default:false)
Protocols
Inspect, Enumerable, and Collectable protocols are automatically
implemented to mimic plain map behaviour.
If Jason is compiled and available, Jason.Encoder is also derived.