Optional type hints
cschmatzler opened this issue · comments
Environment
- Elixir version (elixir -v): Elixir 1.14.4 (compiled with Erlang/OTP 25)
- Nestru version (mix deps | grep nestru | head -1): nestru 0.3.3 (Hex package) (mix)
Actual behavior
Having a struct defined like:
defmodule Kratos.Models.UIContainer do
@moduledoc false
@derive {Nestru.Decoder, hint: %{nodes: [Kratos.Models.UINode], messages: [Kratos.Models.UIText]}}
defstruct [
:action,
:method,
:nodes,
:messages
]
@type t :: %__MODULE__{
:action => String.t(),
:method => String.t(),
:nodes => [Kratos.Models.UINode.t()],
:messages => [Kratos.Models.UIText.t()] | nil
}
end
the messages
attribute can either be a list or nil
.
Currently, when messages
comes back as nil
from the API, I am expectedly getting a
{:error,
%{
get_in_keys: [#Function<8.65378251/3 in Access.key!/1>,
#Function<8.65378251/3 in Access.key!/1>],
message: %{message: "The first argument should be a list. Got nil instead."},
path: ["ui", :messages]
}}
response.
Expected behavior
Is there a way to handle optional hints? Something like
@derive {Nestru.Decoder,
hint: %{
nodes: [Kratos.Models.UINode],
},
hint_optional: %{
messages: [Kratos.Models.UIText]
}}
maybe.
I guess you might want to replace nil with a default empty list to process it without an error message at all. To do so you can adapt Nestru.PreDecoder
protocol like the following:
defmodule Kratos.Models.UIContainer do
@moduledoc false
defimpl Nestru.PreDecoder do
def gather_fields_from_map(_value, _context, map) do
{:ok, Map.update(map, "messages", [], &if(is_nil(&1), do: [], else: &1))}
end
end
@derive {Nestru.Decoder, hint: %{nodes: [Kratos.Models.UINode], messages: [Kratos.Models.UIText]}}
...
end
Then the decoding of the map with missing messages
field or when its value is set to null will return:
{:ok,
%Kratos.Models.UIContainer{
...
messages: []
}}
How about that?
That works beautifully, sorry for missing it in the first place. Thanks!