Дублированные модули: 'Elixir.Poison.Encoder.Map', указанный в яде `mix release` - PullRequest
0 голосов
/ 04 июля 2018

Я работаю в зонтичном приложении, которое работает с Poison для кодирования и декодирования Json. Чтобы закодировать мои экто-модели, я пишу следующую реализацию:

def defimpl Poison.Encoder, for: Any do
def encode(%{__struct__: App.Models.Task} = struct, options) do
  struct =
    if struct.geom do
      {lon, lat} =  struct.geom.coordinates
      %{struct | lon: lon, lat: lat}
    else
      struct
    end
  enconde_model(struct, options)
end

def encode(%{__struct__: _} = struct, options) do
  enconde_model(struct, options)
end

def encode({lon, lat}, options) when is_float(lon) and is_float(lat) do
  %{lon: lon, lat: lat}
  |> sanitize_map()
  |> Poison.Encoder.Map.encode(options)
end

defp enconde_model(model, options) do
  model
  |> Map.from_struct()
  |> sanitize_map()
  |> Poison.Encoder.Map.encode(options)
end

defp sanitize_map(map) do
  map
  |> Enum.filter(
    fn({_, %Ecto.Association.NotLoaded{}}) -> false
      ({:__meta__, _}) -> false
      ({:__struct__, _}) -> false
      ({_, _}) -> true
    end)
  |> Map.new()
end

конец

Смысл в том, что после запуска mix release программа выдаст ошибку, если я не закомментирую код, который я только что показал выше.

Итак, есть еще один способ достичь этой же функциональности без использования реализации?

1 Ответ

0 голосов
/ 04 июля 2018

Вы получаете эту ошибку, потому что переопределяете существующие реализации кодировщика. Правильный способ сделать это - реализовать Poison.Encoder для каждой структуры, которую вы хотите кодировать. С @derive это довольно просто:

@derive {Poison.Encoder, only: [:the, :field, :names, :you, :want, :in, :json]}
schema "tasks" do
  ...
end

Для кортежа вам необходимо вручную преобразовать их в карты в кодировке для структур, которые могут содержать эти кортежи:

defimpl Poison.Encoder, for: Something do
  def encode(%{a_tuple: {lat, lon}, something: else_}, options) do
    Poison.encode!(%{location: %{lat: lat, lon: lon}, something: else_}, options)
  end
end
...