我是Elixir / Phoenix的新手,并试图通过构建一个小应用程序来学习。
我从第三方API获取数据并继续收到以下错误。
(ArgumentError) argument error :erlang.iolist_to_binary([%{"24h_volume" => "1000", "name" => "some_name"},{...}])
我在控制器中拥有的是:
HTTPoison.start
%HTTPoison.Response{body: body} = HTTPoison.get!(url)
body = body
|> Poison.decode!(keys: :atoms!)
这不起作用。我使用了(键::: atoms),这在毒药文档中是不鼓励的。
这是我的架构:
schema "things" do
field :name, :string
field :volume_24h, :float
timestamps()
end
@doc false
def changeset(%Thing{} = thing, attrs) do
thing
|> cast(attrs, [:volume_24h, :name])
|> validate_not_nil([:volume_24h, :name])
end
def validate_not_nil(changeset, fields) do
Enum.reduce(fields, changeset, fn field, changeset ->
if get_field(changeset, field) == nil do
add_error(changeset, field, "nil")
else
changeset
end
end)
end
我试图为“24h_volume”使用不同的字段名称,我收到此错误:
(ArgumentError) argument error :erlang.binary_to_existing_atom("24h_volume", :utf8)
我在这里显然遗漏了一些东西。
有没有办法将所需的字段名称传递给Poison,因为“24h_volume”不是有效的原子?我该如何解决这些错误?
你有一个混乱的volume_24h
参数。
正如Poison
documentation所述:
请注意,
keys: :atoms!
重用现有原子,即如果在调用之前未分配:name
,则会遇到参数错误消息。
这正是发生的事情。应用程序期望:volume_24h
密钥来自请求,但它(由于某种原因,可能由于形式错误配置等)接收24h_volume
。通过使用宽松的atoms
调用而不是atoms!
你没有解决任何问题,你就隐藏了这个问题。实际发生了什么,24h_volume
密钥来了,并被cast
的调用有效地丢弃。
你需要的是修复fronend /请求发送者发送volume_24h
密钥,或修复控制器接受:"24h_volume"
密钥。
劝阻使用atoms
背后有两个原因。在Poison
文档中描述了一个:所谓的“原子DOS攻击”是可能的随机请求随后发出随机密钥,溢出原子存储。第二个是通过使用banged版本atoms!
,可以保护自己免受上述错误的错误配置。
FWIW,正确密钥的原子正在模式定义中分配。
你有你如下定义你的原子,因为你的原子通常是一个非常开始的数字,但你可以通过用"
包裹它来绕过它
所以改变你的原子如下:
:"24_volume"