Create a struct from a map within Elixir

With Elixir, we can create a struct which is a data type similar to a map except it ensures only a given set of key / value pairs are present.

Converting from a struct to a map is fairly simple.


But doing the reverse programmatically isn’t possible with the standard library. Personally, I feel its a good design decision because:

  • Structs can only use atoms as keys. Maps can use any data type including processes identifiers, references, functions, and other complex data types. Within an application its easy to say a string key “hello” is same as the a atom key :hello, but a language creator may not want to make the same assumptions about application internals.
  • If a map contains keys not present in the struct, the behavior of a converter is undefinable by a language creator. Should it ignore extra keys? Should it throw an error?

That said….

When designing an application its a good practice to handle data from outside sources as Maps, then immediately convert it to a Struct within your own code.

I wanted to convert a map to a given struct while:

  • Ignoring keys not found
  • Treating string keys within the map as if they were atoms. So %{“hello” => “world”} is treated the same as %{:hello => “world”}
  • Merging the valid keys into the struct, which preserves default values if a key isn’t present.

Here’s a code.

def struct_from_map(a_map, as: a_struct) do
# Find the keys within the map
keys = Map.keys(a_struct)
|> Enum.filter(fn x -> x != :__struct__ end)
  # Process map, checking for both string / atom keys
processed_map =
for key <- keys, into: %{} do
value = Map.get(a_map, key) || Map.get(a_map, to_string(key))
{key, value}
  a_struct = Map.merge(a_struct, processed_map)

Given a struct defined as:

defmodule User do
defstruct [
username: ""

Convert it with:

struct_from_map(%{"username": "Me!"}, as: %User{})

Hopefully, someone finds this useful enough to use.

The above code is MIT Licenced.

— —

Edit: 3/30/2016.

For a more general solution, please check out the beautiful ExConstructor library.

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.