将映射转换为URI查询字符串

时间:2017-02-27 05:40:15

标签: elixir reduce

我有一个Elixir Map

m1 = %{a: 1, b: "fsfd", c: 123}

我想将其转换为URI的查询字符串。

a=1&b=fsfd&c=123

我该怎么做?我试过这个:

Enum.reduce(m1, fn({k, v}, acc) -> "#{acc}&{k}=#{v}" end)

但它没有用,因为acc没有按预期匹配模式。

3 个答案:

答案 0 :(得分:2)

您可以使用:

URI.encode_query(%{a: 1, b: 2, c: "fdsfds"})

答案 1 :(得分:0)

您的代码存在的问题是您使用的是Enum.reduce/2而不是Enum.reduce/3。您传递的函数在n - 1中执行reduce/2次,第一个值用作accumulator的初始值。

因此,对于您的地图,累加器的初始值将为{:a, 1},这是一个不实现String.Chars协议的元组。您可以通过提供初始累加器值来解决此问题:

Enum.reduce(m1, "", fn({k, v}, acc) -> "#{acc}&{k}=#{v}" end)
<2> Elixir的内置方法:

作为@Dogbert pointed out,您可以使用URI.encode_query/1而不是自己编写:

iex> URI.encode_query(%{foo: 1, bar: 2, baz: "value with spaces"})
"foo=1&bar=2&baz=value+with+spaces"

答案 2 :(得分:0)

OP的问题有一个简单的示例map,其中未包含值的集合,因此,如果您要根据URI标准对URI.encode_query(%{a: 1, b: 2})进行编码,则map的答案是正确的。 / p>

但是,URI.encode_query/1不支持具有列表值的地图,并且你们中的很多人将使用Phoenix和/或Plug,因此使用Plug启用了将查询字符串变成{{1} }放入值列表:a[]=1&a[]=2。对于您来说,有:

[1, 2]