Elixir用毒药解码

时间:2017-11-29 16:45:28

标签: json elixir decode elixir-poison

我从我的数据库中获取此字符串作为查询结果:

"%Sample.Struct{list: [], total: \"0.00\", day: 6, id: \"8vfts6\"}"

有没有办法将这个转换回地图? 我得到这个错误用毒药解码它

** (Poison.SyntaxError) Unexpected token: %
(poison) lib/poison/parser.ex:56: Poison.Parser.parse!/2
(poison) lib/poison.ex:83: Poison.decode!/2

我无法修复数据添加到数据库的方式,我必须找到一种适当的方法来使键/值路由轻松地从中检索数据。 (这只是一个更复杂结果的样本)

1 个答案:

答案 0 :(得分:2)

正如评论中提到的那样,您不应该使用Code.eval_string。但是,有一种方法可以使用Code模块安全地将代码转换为Elixir结构:

ex(1)> encoded = "%Sample.Struct{list: [], total: \"0.00\", day: 6, id: \"8vfts6\"}"
"%Sample.Struct{list: [], total: \"0.00\", day: 6, id: \"8vfts6\"}"

首先,从字符串中获取AST,但使用模式匹配以确保它是您正在寻找的结构({:__aliases__, _, [:Sample, :Struct]})。所有其他(可能是恶意的)代码都将失败此匹配:

iex(2)> {:ok, {:%, _, [{:__aliases__, _, [:Sample, :Struct]}, {:%{}, _, keymap}]} = ast} = Code.string_to_quoted(encoded)
{:ok,
 {:%, [line: 1],
  [{:__aliases__, [line: 1], [:Sample, :Struct]},
   {:%{}, [line: 1], [list: [], total: "0.00", day: 6, id: "8vfts6"]}]}}

这里有结构astkeymap。您现在可能想要使用eval_quoted和AST,以获得所需的结构:

iex(3)> {struct, _} = Code.eval_quoted(ast)
{%Sample.Struct{day: 6, id: "8vfts6", list: [], total: "0.00"}, []}
iex(4)> struct
%Sample.Struct{day: 6, id: "8vfts6", list: [], total: "0.00"}

但它仍然不安全!有人可能会将一个导致副作用的函数放入字符串中,例如"%Sample.Struct{list: IO.puts \"Something\"}",这将在评估期间执行。所以你需要检查keymap第一,如果它包含安全数据

或者您可以直接使用keymap,而无需评估任何内容:

iex(5)> struct(Sample.Struct, keymap)                                                                                    
%Sample.Struct{day: 6, id: "8vfts6", list: [], total: "0.00"}