用毒药解码长生不老药
Elixir decode with Poison
我从我的数据库中得到这个字符串作为查询结果:
"%Sample.Struct{list: [], total: \"0.00\", day: 6, id: \"8vfts6\"}"
有什么方法可以将这张图转换回地图吗?
我在用 poison
解码时遇到这个错误
** (Poison.SyntaxError) Unexpected token: %
(poison) lib/poison/parser.ex:56: Poison.Parser.parse!/2
(poison) lib/poison.ex:83: Poison.decode!/2
我无法修复将数据添加到数据库的方式,我必须找到一种 key/value 路由的正确方法,以便轻松地从中检索数据。 (这只是一个更复杂结果的示例)
正如评论中提到的,您不应该使用 Code.eval_string
。但是,有一种方法可以安全地将代码转换为 Elixir 结构,使用 Code
模块:
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"]}]}}
这里有完整的 ast
和 keymap
。您现在可能想要将 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"}
我从我的数据库中得到这个字符串作为查询结果:
"%Sample.Struct{list: [], total: \"0.00\", day: 6, id: \"8vfts6\"}"
有什么方法可以将这张图转换回地图吗? 我在用 poison
解码时遇到这个错误** (Poison.SyntaxError) Unexpected token: %
(poison) lib/poison/parser.ex:56: Poison.Parser.parse!/2
(poison) lib/poison.ex:83: Poison.decode!/2
我无法修复将数据添加到数据库的方式,我必须找到一种 key/value 路由的正确方法,以便轻松地从中检索数据。 (这只是一个更复杂结果的示例)
正如评论中提到的,您不应该使用 Code.eval_string
。但是,有一种方法可以安全地将代码转换为 Elixir 结构,使用 Code
模块:
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"]}]}}
这里有完整的 ast
和 keymap
。您现在可能想要将 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"}