-
Notifications
You must be signed in to change notification settings - Fork 1
Open
Description
Hi, thanks for this library. 🙂
It works well but it does not enforce fields that are declared in the struct to be enforced.
Imagine this struct:
defmodule Person do
@enforce_keys [:name]
defstruct name: nil,
age: nil,
happy?: true,
phone: nil
@type t() :: %__MODULE__{
name: String.t(),
age: non_neg_integer() | nil,
happy?: boolean(),
phone: String.t() | nil
}
endNow if you evaluate
data = %{"age" => 42, "happy?" => true, "phone" => "(206) 342-8631"}
Forma.parse(data, Person)you get
{:ok, %Person{age: 42, happy?: true, name: nil, phone: "(206) 342-8631"}}Notice that the call was successful and :name is set to nil even though it is in @enforced_keys and its type is not nullable.
Instead, if you evaluate %Person{age: 42, happy?: true, phone: "(206) 342-8631"}, you get this error: (ArgumentError) the following keys must also be given when building struct Person: [:name].
I think Forma should enforce :name being present in data as well. What do you think?
I think it could be achieved by changing the struct clause for Forma.Parser.parse!/3 from this:
def parse!(input, parsers, {:struct, name, fields}) do
case input do
input when is_map(input) -> map_exact_fields!(input, parsers, struct(name), fields)
_ -> raise "not a map #{inspect(input)}"
end
endto something like this:
def parse!(input, parsers, {:struct, name, fields}) do
case input do
input when is_map(input) -> map_exact_fields!(input, parsers, %{}, fields) |> then(&struct!(name, &1))
_ -> raise "not a map #{inspect(input)}"
end
endMetadata
Metadata
Assignees
Labels
No labels