- Notifications
You must be signed in to change notification settings - Fork7
ruby2elixir/atomic_map
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
A small utility to convert Elixir maps with mixed string/atom keys to atom-only keyed maps. Optionally with a safe option, to preventatom space exhaustion of the Erlang VM. Since v0.8 it also supports conversion of keys fromCamelCase
tounder_score
format.
AtomicMap can convert simple maps or nested structures such as lists of maps; seeNested Structures below for examples.
With no options, it safely converts string keys in maps to atoms, usingString.to_existing_atom/1
.
iex>AtomicMap.convert(%{"a"=>"a","b"=>"b",c:"c"})%{a:"a",b:"b",c:"c"}
Because safe conversion usesString.to_existing_atom/1
, it will raise when the target atom does not exist.
iex>AtomicMap.convert(%{"abcdefg"=>"a","b"=>"b"})**(ArgumentError)argumenterror:erlang.binary_to_existing_atom("abcdefg",:utf8)
To have safe conversion can ignore unsafe keys, leaving them as strings, passtrue
for theignore
option.
iex>AtomicMap.convert(%{"abcdefg"=>"a","b"=>"b"},%{ignore:true})%{:b=>"b","abcdefg"=>"a"}
To disable safe conversion and allow new atoms to be created, passfalse
for thesafe:
option.(This makes theignore
option irrelevant.)If the input is user-generated, converting only expected keys will prevent excessive atom creation.
iex>map=%{"expected_key"=>"a","b"=>"b","unexpected_key"=>"c"}%{"expected_key"=>"a","b"=>"b","unexpected_key"=>"c"}iex>filtered_map=Map.take(map,["expected_key","b"])%{"b"=>"b","expected_key"=>"a"}iex>AtomicMap.convert(filtered_map,%{safe:false})%{b:"b",expected_key:"a"}
By default,"CamelCase"
string keys will be converted tounder_score
atom keys.
iex> AtomicMap.convert(%{ "CamelCase" => "hi" })** (ArgumentError) argument error :erlang.binary_to_existing_atom("camel_case", :utf8)
Note that"camel_case"
was the string that failed conversion.If that atom is explicitly created first, the conversion will succeed.
iex>:camel_case:camel_caseiex>AtomicMap.convert(%{"CamelCase"=>"hi"})%{camel_case:"hi"}
Allowing unsafe conversions will also work.If the input is user-generated, converting only expected keys will prevent excessive atom creation.
iex>map=%{"CamelCase"=>"a","b"=>"b","AnotherCamelCase"=>"c"}%{"CamelCase"=>"a","b"=>"b","AnotherCamelCase"=>"c"}iex>filtered_map=Map.take(map,["CamelCase","b"])%{"b"=>"b","CamelCase"=>"a"}iex>AtomicMap.convert(filtered_map,%{safe:false})%{b:"b",camel_case:"a"}
"hyphenated-string"
keys will always be converted tounder_score
atom keys.There is currently no way to disable this behavior.
iex>AtomicMap.convert(%{"some-key"=>"a","b"=>"c"})**(ArgumentError)argumenterror:erlang.binary_to_existing_atom("some_key",:utf8)
Note that"some_key"
was the string that failed conversion.If that atom is explicitly created first, the conversion will succeed.
iex>:some_key:some_keyiex>AtomicMap.convert(%{"some-key"=>"a","b"=>"c"})%{b:"c",some_key:"a"}
Allowing unsafe conversions will also work.If the input is user-generated, converting only expected keys will prevent excessive atom creation.
iex>map=%{"some-key"=>"a","b"=>"b","another-key"=>"c"}%{"some-key"=>"a","b"=>"b","another-key"=>"c"}iex>filtered_map=Map.take(map,["some-key","b"])%{"b"=>"b","some-key"=>"a"}iex>AtomicMap.convert(filtered_map,%{safe:false})%{b:"b",some_key:"a"}
# works with nested mapsiex>AtomicMap.convert(%{"a"=>2,"b"=>%{"c"=>4}})%{a:2,b:%{c:4}}# works with nested maps + lists + mixed key types (atoms + binaries)iex>AtomicMap.convert([%{"c"=>1},%{:c=>2},%{"c"=>%{:b=>4}}],%{safe:true})[%{c:1},%{c:2},%{c:%{b:4}}]
Add atomic_map to your list of dependencies in
mix.exs
:def deps do[{:atomic_map, "~> 0.8"}]end
- maybe allow direct conversion to a struct, like Poison does it: as: %SomeStruct{}...
$ mix bench