Skip to content

Instantly share code, notes, and snippets.

@poteto
Last active April 20, 2018 16:52
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save poteto/e5068020fea38f3594acf1e15cee89fb to your computer and use it in GitHub Desktop.
Save poteto/e5068020fea38f3594acf1e15cee89fb to your computer and use it in GitHub Desktop.
Flatten deeply nested Map in Elixir
defmodule Json do
def flatten(%{} = json) do
json
|> Map.to_list()
|> to_flat_map(%{})
end
def flatten(%{} = json) when json == %{}, do: %{}
defp to_flat_map([{_k, %{} = v} | t], acc), do: to_flat_map(Map.to_list(v), to_flat_map(t, acc))
defp to_flat_map([{k, v} | t], acc), do: to_flat_map(t, Map.put_new(acc, k, v))
defp to_flat_map([], acc), do: acc
end
%{id: "1", foo: %{bar: %{qux: "hello world"}, baz: 123}}
|> Json.flatten()
|> IO.inspect()
# %{baz: 123, id: "1", qux: "hello world"}
@jon4syth
Copy link

jon4syth commented Apr 20, 2018

The second clause will never be matched: def flatten(%{} = json) when json == %{}, do: %{} because just as = will match successfully for any two maps, == returns true for any two maps. Use Map.equal?/2 to find if two maps are identical. This doesn't work in guard clauses though (i.e.when). So you probably have to check for an empty map inside the function body (if that is what the second flatten clause is intended to do).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment