如何将Erlang对象结构转换为Elixir Map?

时间:2016-11-28 13:19:37

标签: erlang elixir jiffy

我正在使用couchbeam与Elixir联系CouchDB。

但是lib让我回到了旧的erlang对象表示,如{[{"foo", "bar"}]}而不是elixir地图,这是由于lib使用jiffy:decode而不是return_maps,如何将此对象结构转换为Elixir地图(反之亦然)?

我发现了jiffy的一种破解方式:编码和jiffy:用return_maps再次解码...但是必须有另一种选择吗?

更新

来自Hynek在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]}

2 个答案:

答案 0 :(得分:4)

我不知道Elixir但是在Erlang中:

-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}]}
...

答案 1 :(得分:0)

我需要确定您的所有数据结构,但您可以使用以下内容:

iex(1)> Enum.into([{"foo", "bar"}], %{})
%{"foo" => "bar"}