【问题标题】:Poison : unable to encode value毒药:无法编码值
【发布时间】:2018-04-13 16:42:37
【问题描述】:

我无法对从 Ecto 查询结果毒药编码方法获得的值进行编码

控制器代码:

def companies(conn, params) do
    companies = Repo.all(
      from(
        c in Company,
        select: {c.name, c.uid},
        limit: 20
      )
    ) 

    conn
    |> put_resp_header("content-type", "application/json; charset=utf-8")
    |> send_resp(200, Poison.encode!(companies, pretty: true))
end

模板代码:

<div class="form-group row">
  <%= label f, :company_id, class: "control-label" %>
  <%= select f, :company_id, @companies, class: "form-control"%>
<%= error_tag f, :company_id %>

错误信息:

Request: GET /companies
** (exit) an exception was raised:
    ** (Poison.EncodeError) unable to encode value: {"Loews Corporation", 1000285930}
        (poison) lib/poison/encoder.ex:383: Poison.Encoder.Any.encode/2
        (poison) lib/poison/encoder.ex:268: anonymous fn/4 in Poison.Encoder.List.encode/3
        (poison) lib/poison/encoder.ex:269: Poison.Encoder.List."-encode/3-lists^foldr/2-0-"/3
        (poison) lib/poison/encoder.ex:269: Poison.Encoder.List.encode/3
        (poison) lib/poison.ex:41: Poison.encode!/2

【问题讨论】:

  • 我认为这是您返回的元组的问题,您是否尝试过对地图进行编码?类似:select: %{name: c.name, uid: c.uid}

标签: json elixir ecto elixir-poison


【解决方案1】:

Poison 无法将元组编码为 JSON 值。如果您想在结果 JSON 中使用 [{name: ..., uid: ...}, {name: ..., uid: ...}],您可以在查询中使用 map()select 中的映射文字:

select: map(c, [:name, :uid])

select: %{name: c.name, uid: c.uid}

【讨论】:

  • 它工作,但任何关于错误的想法:协议 Phoenix.HTML.Safe 没有为 %{name: 实现
  • 在您发送 JSON 响应的问题代码中。你从哪里调用这个模板代码?
  • 所以在同一个表单上,我调用自动完成搜索
  • 在我对 Enum.map(&{&1.name, &1.uid}), class: "form -控制"%>
【解决方案2】:

添加到@Dogbert 的答案:您还可以通过从手动返回的Ecto 中生成map 来生成JSON 对象:

companies =
  from(c in Company, select: {c.name, c.uid}, limit: 20)
  |> Repo.all()     # returning list of tuples
  |> Enum.into(%{}) # this

#⇒ %{"Loews Corporation" => 1000285930, "Foo" => 1, "Bar" => 2}

可以使用Poison 将地图编码为 JSON,从而生成 JS 对象。

【讨论】:

    猜你喜欢
    相关资源
    最近更新 更多
    热门标签