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

问题描述 投票:1回答:2

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

elixir phoenix-framework elixir-poison httpoison
2个回答
1
投票

你有一个混乱的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,正确密钥的原子正在模式定义中分配。


2
投票

你有你如下定义你的原子,因为你的原子通常是一个非常开始的数字,但你可以通过用"包裹它来绕过它

所以改变你的原子如下:

:"24_volume"
© www.soinside.com 2019 - 2024. All rights reserved.