Transmog v0.1.1 Transmog View Source
Transmog
is a module which provides the ability to map keys on nested maps,
lists and structs to new values. It is useful for when you have external data
that you want to convert into an internal format easily. This recursive
transformation is made using an internal concept known as key pairs.
Key Pairs
Key pairs are a list of two-tuples which represent a mapping from a key in the source map to a key in the destination map. The key mapping does not have to be exhaustive and any values that are skipped are simply added to the result.
Examples
#=> "credentials", "first_name" to :identity, :first_name
[{["credentials", "first_name"], [:identity, :first_name]}]
When key pairs are simple they can be represented using an internal DSL which
is a dot notation string. These dot notation strings also support atoms if you
prefix them with :
.
Examples
#=> Same as the previous example
[{"credentials.first_name", ":identity.:first_name"}]
Parsing
All of the supported key pair formats implement the Transmog.Parser
protocol. Technically if you wanted to add support for a different type then
you could implement the protocol for them.
Formatting
We validate key pairs when they are provided to the main entrypoint of the
library, format/2
and format!/2
. If the key pairs are not valid then we
will let you know with an error.
Examples
#=> Notice: key paths must be equal length!
iex> key_paths = [{"credentials", ":identity.:first_name"}]
iex> Transmog.format(%{"credentials" => "Mike Rudolph"}, key_paths)
{:error, :invalid_key_pairs}
iex> key_paths = [{"", ":last_name"}]
iex> Transmog.format(%{}, key_paths)
{:error, :invalid_key_path}
Once your key pairs are validated you can start to use them to transform your nested maps and lists.
Examples
#=> Notice: you need to be explicit about which keys you want updated
iex> key_paths = [
...> {"credentials", ":identity"},
...> {"credentials.first_name", ":identity.:first_name"}
...> ]
iex> source = %{"credentials" => %{"first_name" => "Tom"}}
iex> {:ok, result} = Transmog.format(source, key_paths)
iex> result
%{identity: %{first_name: "Tom"}}
iex> key_paths = [
...> {"credentials", ":identity"},
...> {"credentials.first_name", ":identity.:first_name"}
...> ]
iex> source = [
...> %{"credentials" => %{"first_name" => "John"}},
...> %{"credentials" => %{"first_name" => "Sally"}}
...> ]
iex> {:ok, result} = Transmog.format(source, key_paths)
iex> result
[%{identity: %{first_name: "John"}}, %{identity: %{first_name: "Sally"}}]
If you know that your key pairs are valid then you can use format!/2
instead
and your results will be unwrapped automatically for you.
Examples
iex> key_paths = [{"name", ":name"}]
iex> source = %{"name" => "Jimmy"}
iex> Transmog.format!(source, key_paths)
%{name: "Jimmy"}
You can even transform your structs. When a struct is encountered during the parse it will be converted into a map automatically for you.
Link to this section Summary
Types
key_paths/0
is the type for a single tuple of key paths. Both sides can
be any type as long as they can be parsed by Transmog.Parser
.
Functions
format/2
takes a source value and either a list of key paths or a
Transmog.KeyPair
struct directly and performs the key transformation on the
value.
format!/2
takes a source value and either a list of key paths or a
Transmog.KeyPair
struct directly and performs the key transformation on the
value.
Link to this section Types
key_paths/0
is the type for a single tuple of key paths. Both sides can
be any type as long as they can be parsed by Transmog.Parser
.
Link to this section Functions
format(source, key_pairs)
View Sourceformat(source :: term(), mapping :: Transmog.KeyPairs.t() | [key_paths()]) :: {:ok, term()} | Transmog.KeyPairs.error()
format/2
takes a source value and either a list of key paths or a
Transmog.KeyPair
struct directly and performs the key transformation on the
value.
If the key paths are given then they will be parsed using
Transmog.KeyPairs.parse/1
and will report errors if any occur during that.
Examples
iex> key_paths = [{"a", ":a"}, {"a.b", ":a.:b"}]
iex> source = %{"a" => %{"b" => "c"}}
iex> {:ok, result} = Transmog.format(source, key_paths)
iex> result
%{a: %{b: "c"}}
iex> key_paths = [{"a", ":a"}, {"a.b", ":a.:b"}]
iex> {:ok, %Transmog.KeyPairs{} = key_pairs} = Transmog.KeyPairs.parse(key_paths)
iex> source = %{"a" => %{"b" => "c"}}
iex> {:ok, result} = Transmog.format(source, key_pairs)
iex> result
%{a: %{b: "c"}}
format!(source, key_pairs)
View Sourceformat!(source :: term(), mapping :: Transmog.KeyPairs.t() | [key_paths()]) :: term()
format!/2
takes a source value and either a list of key paths or a
Transmog.KeyPair
struct directly and performs the key transformation on the
value.
This function will raise an error if the Transmog.KeyPair
struct cannot be
created by parsing the key paths. The result will be automatically unwrapped
if the operation is successful.
Examples
iex> key_paths = [{"a", ":a"}, {"a.b", ":a.:b"}]
iex> source = %{"a" => %{"b" => "c"}}
iex> Transmog.format!(source, key_paths)
%{a: %{b: "c"}}
iex> key_paths = [{"a", ":a"}, {"a.b", ":a.:b"}]
iex> %Transmog.KeyPairs{} = key_pairs = Transmog.KeyPairs.parse!(key_paths)
iex> source = %{"a" => %{"b" => "c"}}
iex> Transmog.format!(source, key_pairs)
%{a: %{b: "c"}}