用胖箭头vs冒号映射(毒药 - json解码)

Nem*_* Ga 9 elixir elixir-poison

ab = %{a: 1}
ac = %{"a" => 1}
Run Code Online (Sandbox Code Playgroud)

究竟有什么区别?为什么Poison.decode!返回格式#2(我需要#1与Ecto.Changeset.change一起使用).

Json响应来自API,看起来像

[{"a":3}]
Run Code Online (Sandbox Code Playgroud)

The*_*Anh 15

ab = %{a: 1} # atom key you can access it like ab.a
ac = %{"a" => 1} # string key you can access it ac["a"]
Run Code Online (Sandbox Code Playgroud)

Poison.decode!返回格式#2:

从广义上讲,来自应用程序外部的数据是不可信任的.鉴于原子分配可能导致长时间运行的Erlang系统中的内存耗尽,使用原子作为外部数据会打开您的应用程序以进行潜在的拒绝服务(DoS)攻击.

这个事实反映在许多Elixir库中,例如流行的JSON解析器Poison.在将外部数据转换为内部数据结构时,性能良好的库通常会使用字符串作为映射键

如果要将地图键从字符串转换为原子.您可以这样做:

iex> maps = %{"foo" => "bar"}
%{"foo" => "bar"}
iex> for {key, val} <- maps, into: %{}, do: {String.to_atom(key), val}
%{foo: "bar"}
Run Code Online (Sandbox Code Playgroud)

  • 使用`String.to_existing_atom/1`,有点安全.使用`String.to_atom/1`将打开这个答案中提到的漏洞. (3认同)
  • 此外,通过原子键访问值,如示例中的"ab.a",也可以使用`ab [:a]`来完成.括号语法是更通用的访问语法,而点语法是可用于地图和结构的糖,当键是原子时. (2认同)