Как преобразовать структуру объекта Erlang в карту Elixir?

Я использую couchbeam для связи с CouchDB из Elixir.

Но библиотека возвращает мне старое представление объекта erlang, такое как {[{"foo", "bar"}]}, а не карты эликсира, это было связано с тем, что библиотека использовала jiffy:decode без return_maps. Как мне преобразовать эту структуру объекта в карты Elixir (и наоборот)?

Я нашел хакерский способ jiffy:encode и jiffy:decode снова с помощью return_maps ... Но должна ли быть другая альтернатива?

Обновлять:

Из примера Хайнека в erlang, похоже, это работает:

defmodule ToMaps do

  def convert({x}) when is_list(x) do
    Map.new(x, fn {k, v} -> {k, convert(v)} end)
  end

  def convert([head | tail]) do
    [convert(head) | convert(tail)]
  end

  def convert(x) do
    x
  end
end

Кажется, делает работу.

iex(1)> ToMaps.convert({[{"foo",[{[{"a",1}]},3]},{"bar","baz"}]})

%{"bar" => "baz", "foo" => [%{"a" => 1}, 3]}

person Vasu Mahesh    schedule 28.11.2016    source источник


Ответы (2)


Я не знаю Эликсира, но в Эрланге:

-module(to_maps).

-export([to_maps/1]).

to_maps({L}) when is_list(L) ->
    maps:from_list([{K, to_maps(V)} || {K, V} <- L]);
to_maps([H|T]) ->
    [to_maps(H) | to_maps(T)];
to_maps(X) -> X.

Изменить:

Обратный:

from_maps(#{} = M) ->
    F = fun(K, V, Acc) -> [{K, from_maps(V)} | Acc] end,
    {maps:fold(F, [], M)};
from_maps([H|T]) ->
    [from_maps(H) | from_maps(T)];
from_maps(X) -> X.

Я бы не рекомендовал это, но это может быть даже одна функция:

convert({L}) when is_list(L) ->
    maps:from_list([{K, convert(V)} || {K, V} <- L]);
convert(#{} = M) ->
    F = fun(K, V, Acc) -> [{K, convert(V)} | Acc] end,
    {maps:fold(F, [], M)};
convert([H|T]) ->
    [convert(H) | convert(T)];
convert(X) -> X.

Использование:

1> jiffy:decode(<<"{\"foo\":[3, {\"a\":1}], \"bar\":\"baz\"}">>).
{[{<<"foo">>,[3,{[{<<"a">>,1}]}]},{<<"bar">>,<<"baz">>}]}
2> to_maps:to_maps(v(-1)).
#{<<"bar">> => <<"baz">>,<<"foo">> => [3,#{<<"a">> => 1}]}
3> to_maps:from_maps(v(-1)).
{[{<<"foo">>,[3,{[{<<"a">>,1}]}]},{<<"bar">>,<<"baz">>}]}
4> to_maps:convert(v(-1)).
#{<<"bar">> => <<"baz">>,<<"foo">> => [3,#{<<"a">> => 1}]}
5> to_maps:convert(v(-1)).
{[{<<"foo">>,[3,{[{<<"a">>,1}]}]},{<<"bar">>,<<"baz">>}]}
6> to_maps:convert(v(-1)).
#{<<"bar">> => <<"baz">>,<<"foo">> => [3,#{<<"a">> => 1}]}
...
person Hynek -Pichi- Vychodil    schedule 28.11.2016
comment
Я попробовал код в эликсире, аналогичный этому подходу, отредактировав свой вопрос. - person Vasu Mahesh; 28.11.2016
comment
@VasuMahesh Я думаю, что во втором функциональном предложении должно быть [convert(head) | convert(tail)]. - person Hynek -Pichi- Vychodil; 28.11.2016
comment
Да, спасибо, что заметили, а что будет наоборот? от Maps до этой структуры? Так как в кушбиме при сохранении документа я не могу отдать карты erlang/elixir - person Vasu Mahesh; 30.11.2016
comment
@VasuMahesh: см. Изменить, но считайте convert/1 шуткой и не делайте этого. - person Hynek -Pichi- Vychodil; 30.11.2016

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

iex(1)> Enum.into([{"foo", "bar"}], %{})
%{"foo" => "bar"}
person slashmili    schedule 28.11.2016
comment
Привет! спасибо за ответ, см. пример Hynek -Pichi- Vychodil для полных данных, если вы можете расшифровать это, это будет работать для одного набора, его пример, кажется, охватывает все. - person Vasu Mahesh; 28.11.2016