Яд: невозможно закодировать значение

Я не могу кодировать значения, которые я получаю из результата запроса Ecto Метод кодирования Poison

Код контроллера:

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 %>

Error message:

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

person Jagdish    schedule 13.04.2018    source источник
comment
Я бы подумал, что это проблема кортежа, который вы возвращаете, вы пытались вместо этого закодировать карту? что-то вроде: select: %{name: c.name, uid: c.uid}   -  person xavvvier    schedule 13.04.2018


Ответы (2)


Poison не может кодировать кортежи в значения JSON. Если вы хотите [{name: ..., uid: ...}, {name: ..., uid: ...}] в результирующем JSON, вы можете использовать map() или литерал карты в select в запросе:

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

or

select: %{name: c.name, uid: c.uid}
person Dogbert    schedule 13.04.2018
comment
Это сработало, но есть идеи об ошибке: протокол Phoenix.HTML.Safe не реализован для %{name: - person Jagdish; 13.04.2018
comment
‹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 %› ‹/div› - person Jagdish; 13.04.2018
comment
В коде вопроса вы отправляете ответ JSON. Откуда вы вызываете этот код шаблона? - person Dogbert; 13.04.2018
comment
Итак, в той же форме я вызываю автозаполнение поиска ‹div class=form-group row› ‹%= label(:user, :country, Country, class: control-label col-sm-2) %› ‹div class= col-sm-10› ‹%= awesomplete(:user, :country, [class: form-control], [ url: rule_set_path(@conn, :companies), loadall: true, prepop: true, minChars: 1, maxItems : 8, значение: имя ]) %› ‹/div› - person Jagdish; 13.04.2018
comment
Это сработало после того, как я внес изменения в форму, например ‹%= select f, :company_id, @companies |› Enum.map(&{&1.name, &1.uid}), class: form-control%› - person Jagdish; 13.04.2018

Добавление к ответу @Dogbert: вы также можете создать объект JSON, создав map из того, что Ecto вернуло вручную:

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}

Карты могут быть закодированы в JSON с помощью Poison, создавая объекты JS.

person Aleksei Matiushkin    schedule 13.04.2018