Reputation: 683
I'm trying to convert a struct to a map to be able to clean all the nil values
I'm currently using this code
case Nadia.get_updates do
{:ok, results} ->
Map.from_struct(results)
|> Enum.filter(fn {_, v} -> v != nil end)
|> Enum.into(%{})
Note: Nadia.get_updates returns the following structure: https://hexdocs.pm/nadia/Nadia.Model.Update.html#t:t/0
Yet I'm always receiving the following error: no function clause matching in Map.from_struct/1
Upvotes: 63
Views: 44865
Reputation: 2569
Since v0.15 we have Map.from_struct/1
which does exactly this.
defmodule User do
defstruct [:name]
end
Map.from_struct(%User{name: "valim"})
#=> %{name: "valim"}
Upvotes: 127
Reputation: 1396
There's another trick
my_struct = %MyStruct{}
my_map = Map.delete my_struct, :__struct__
Upvotes: 17
Reputation: 9099
FWIW, I wrote a library that will do this kind of thing for you automagically w/o having to pull the data structure apart.
https://github.com/philosophers-stone/transform
This is from the test code:
test "implement scrub of empty values from map" do
data = %{ :a => nil, :b => "", :c => "a"}
replace_empty = fn(string, _d) -> if( string == "", do: nil , else: string) end
replace_nil = fn(map, _depth) -> for {k, v} <- map, v != nil , into: %{}, do: {k, v} end
potion = %{ BitString => replace_empty, Map => replace_nil}
assert PhStTransform.transform(data, potion) == %{:c => "a"}
end
Note, if data was a list of maps this would still work just fine. The PhStTransform library will just keep pulling the data apart until it finds a map. In your case you would use a replace_nil function that worked on the kinds of structs you are interested in.
Upvotes: 1
Reputation: 2313
get_updates([{atom, any}]) ::
{:ok, [Nadia.Model.Update.t]} |
{:error, Nadia.Model.Error.t}
If successful it returns a list of Nadia.Model.Update.t. That's why you get that error.
Upvotes: 2