首先,@Olshansk 的回答对我来说就像是一种魅力。谢谢你。
接下来,由于@Olshansk 提供的初始实现缺乏对地图列表的支持,下面是我的代码 sn-p 扩展它。
def keys_to_atoms(string_key_map) when is_map(string_key_map) do
for {key, val} <- string_key_map, into: %{}, do: {String.to_atom(key), keys_to_atoms(val)}
end
def keys_to_atoms(string_key_list) when is_list(string_key_list) do
string_key_list
|> Enum.map(&keys_to_atoms/1)
end
def keys_to_atoms(value), do: value
这是我使用的示例,然后是传递给上述函数后的输出 - keys_to_atoms(attrs)
# Input
%{
"school" => "School of Athens",
"students" => [
%{
"name" => "Plato",
"subjects" => [%{"name" => "Politics"}, %{"name" => "Virtues"}]
},
%{
"name" => "Aristotle",
"subjects" => [%{"name" => "Virtues"}, %{"name" => "Metaphysics"}]
}
]
}
# Output
%{
school: "School of Athens",
students: [
%{name: "Plato", subjects: [%{name: "Politics"}, %{name: "Virtues"}]},
%{name: "Aristotle", subjects: [%{name: "Virtues"}, %{name: "Metaphysics"}]}
]
}
对此的解释很简单。第一个方法是为类型映射的输入调用的所有内容的核心。
for 循环解构键值对中的属性并返回键的原子表示。
接下来,在返回值的同时,又出现了三种可能。
- 值是另一张地图。
- 该值为地图列表。
- 上面的值都不是,是原始的。
所以这一次,当keys_to_atoms方法在赋值时被调用,它可能会根据输入的类型调用这三个方法之一。
这些方法在 sn-p 中以类似的顺序组织。
希望这会有所帮助。干杯!