1

我是 Elixir/Phoenix 的新手,并试图通过构建一个小应用程序来学习。

我正在从第 3 方 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!)

这不起作用。我使用了 (keys: :atoms),这在 Poison 文档中是不鼓励的。

这是我的架构:

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”不是有效的原子?我该如何解决这些错误?

4

2 回答 2

2

您已经将您的原子定义如下,因为您的原子通常以数字开头是非法的,但是您可以通过将其包装来绕过它"

所以改变你的原子如下:

:"24_volume"
于 2017-12-30T23:08:17.273 回答
2

你的volume_24h参数很乱。

正如Poison文档中所述:

请注意,keys: :atoms!重用现有原子,即如果:name在调用之前未分配,您将遇到参数错误消息。

这正是发生的事情。应用程序希望:volume_24h密钥来自请求,但它(出于某种原因,可能是由于 like 的表单配置错误)接收到24h_volume. 通过使用许可atoms调用而不是atoms!您没有解决任何问题,您隐藏了问题。实际发生的情况是,24h_volumekey 来了,并且调用有效地丢弃了cast.

您需要修复前端/请求发送方以发送volume_24h密钥,或修复控制器以接受:"24h_volume"密钥。


atoms不鼓励使用的背后有两个原因。一个在Poison文档中进行了描述:所谓的“原子 DOS 攻击”是可能的,随后发出具有随机密钥的随机请求,从而溢出原子存储。第二个是通过使用 banged 版本,atoms!可以保护自己免受上述错误/错误配置的影响。

FWIW,正确键的原子正在模式定义中分配。

于 2017-12-31T06:37:06.210 回答