从 API 获取数据并使用 Poison 解码时出现参数错误

Getting argument error when fetching data from API and decoding with Poison

我是 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!)

这不起作用。我使用了 Poison 文档中不鼓励使用的 (keys: :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”不是有效原子? 我该如何修复这些错误?

你已经定义了你的 atom 如下,因为你的 atom 通常以数字开头是非法的,但你可以通过用 "

包装它来解决这个问题

所以改变你的原子如下:

:"24_volume"

你的 volume_24h 参数一团糟。

Poison documentation所述:

Note that keys: :atoms! reuses existing atoms, i.e. if :name was not allocated before the call, you will encounter an argument error message.

这正是发生的事情。应用程序期望 :volume_24h 键来自请求,但它(出于某种原因,可能是由于 like 的表单配置错误)收到了 24h_volume。通过使用宽松的 atoms 调用而不是 atoms! 你没有解决任何问题,你 隐藏了问题 。实际发生的是,24h_volume 键出现, 被调用 cast.

有效丢弃

您需要的是修复 fronend/request 发送器以发送 volume_24h 密钥,或者修复控制器以接受 :"24h_volume" 密钥。


不鼓励 atoms 使用的原因有两个。 Poison 文档中描述了一个:所谓的“atoms DOS 攻击”是可能的,随后发出具有随机密钥的随机请求,溢出 atom 存储。第二个是通过使用 banged 版本 atoms! 来保护自己免受 typos/misconfiguration 的影响,就像上面的那样。

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