Case insensitive key retrieval from maps in Elixir

I ran into an issue with inconsistent naming of keys in one of my provider’s json. This is really bad data quality, the data that is being sent should have consistent key names. Either uppper, lower, or capitalized, but consistent. Anyway, this provider was sending data will all kinds of mixed case keys.

Here is some elixir code that I wrote to get keys using a case insensitive match. There is an issue on the Poison decoder project which should render this useless, however till that is fixed you can use the code below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
defmodule CaseInsensitiveGetIn do
def ci_get_in(nil, _), do: nil
def ci_get_in({_k, val}, []), do: val
def ci_get_in({_k, val}, key), do: ci_get_in val, key
def ci_get_in(map, [key|rest]) do
current_level_map = Enum.find(map, &key_lookup(&1, key))
ci_get_in current_level_map, rest
end
def key_lookup({k, _v}, key) when is_binary(k) do
String.downcase(k) == String.downcase(key)
end
end
ExUnit.start
defmodule CaseInsensitiveGetInTest do
use ExUnit.Case
import CaseInsensitiveGetIn
test "gets an exact key" do
assert ci_get_in(%{"name" => "Mujju"}, ~w(name)) == "Mujju"
end
test "gets capitalized key in map" do
assert ci_get_in(%{"Name" => "Mujju"}, ~w(name)) == "Mujju"
end
test "gets capitalized input key in map" do
assert ci_get_in(%{"Name" => "Mujju"}, ~w(Name)) == "Mujju"
end
test "gets mixed input key in map" do
assert ci_get_in(%{"NaME" => "Mujju"}, ~w(nAme)) == "Mujju"
end
test "gets an exact deep key" do
assert ci_get_in(%{"name" => "Mujju", "sister" => %{"name" => "Zainu"}}, ~w(sister name)) == "Zainu"
end
test "gets an mixed case deep map key" do
assert ci_get_in(%{"name" => "Mujju", "sisTER" => %{"naME" => "Zainu"}}, ~w(sister name)) == "Zainu"
end
test "gets an mixed case deep key" do
assert ci_get_in(%{"name" => "Mujju", "sisTER" => %{"naME" => "Zainu"}}, ~w(sIStER NAme)) == "Zainu"
end
test "gets a very deep key" do
map = %{
"aB" => %{
"BC" => 7,
"c" => %{"DD" => :foo, "Cassandra" => :awesome, "MOO" => %{"name" => "Mujju"}}
}}
assert ci_get_in(map, ~w(ab bc)) == 7
assert ci_get_in(map, ~w(ab c dd)) == :foo
assert ci_get_in(map, ~w(ab c moo name)) == "Mujju"
assert ci_get_in(map, ~w(ab Bc)) == 7
assert ci_get_in(map, ~w(ab C dD)) == :foo
assert ci_get_in(map, ~w(ab C mOo nAMe)) == "Mujju"
end
end

I am currently working on Zammu which makes Automatic Deployment of static websites to Github Pages very easy. I would love to get your feedback on it, Use the invitation code KHAJA