在Elixir中映射JSON值

时间:2017-11-17 08:10:02

标签: elixir jsonparser elixir-poison

我使用Posion.decode解析了以下JSON!

json = %{"color-Black|size:10" => 
    %{"attributes" => %{"color" => "Black","size" => "11"},    
      "isAvailable" => true,      
    "pricing" => %{"standard" => "$415.00", "sale" => 415}}, 
 "color|size-EU:9.5" => 
    %{"attributes" => %{"color" => "Black","size" => "11"},    
      "isAvailable" => true,      
    "pricing" => %{"standard" => "$415.00", "sale" => 415}}}

我想映射这个,并且我无法获取JSON元素,因为节点元素中的文本发生了变化。 到目前为止,我已经尝试过了。

Enum.map(json , fn(item) ->
%{
  color: item.attributes["color"],                 
  size: item.attributes["size"],
  price: item.pricing["standard"] * 100,
  isAvailable: item.isAvailable
 }
end)

但是这段代码提供了一些与访问相关的错误。

3 个答案:

答案 0 :(得分:4)

在映射地图时,迭代的键值对作为元组{key, value}来到映射器:

Enum.map(json, fn {_, %{"attributes" => attributes,
                        "isAvailable" => isAvailable,
                        "pricing" => pricing}} ->
  %{
    color: attributes["color"],
    size: attributes["size"],
    price: pricing["standard"],
    isAvailable: isAvailable
   }
end)

#⇒ [
#    %{color: "Black", isAvailable: true, price: "$415.00", size: "11"},
#    %{color: "Black", isAvailable: true, price: "$415.00", size: "11"}
# ]

这里我们使用mapper中的值进行原位模式匹配,以简化匹配器本身的代码,并在输入错误的情况下减少错误。

答案 1 :(得分:2)

三件事:

  1. 你有一张地图,所以Enum.map会给你一个关键和价值元组。你只想要这里的值,所以:

    fn {_, item} ->
    
  2. 地图中的键是字符串。点语法仅适用于原子键。你需要这样做:

    item["attributes"]
    

    而不是

    item.attributes
    

    和其他键类似。

  3. 您的价格是一个字符串。您需要先将其转换为Float才能将其相乘。你可以使用String.trim_leadingString.to_float

    这样做
    iex(1)> "$123.45" |> String.trim_leading("$") |> String.to_float
    123.45
    
  4. Enum.map(json, fn {_, item} ->
      %{
        color: item["attributes"]["color"],
        size: item["attributes"]["size"],
        price: item["pricing"]["standard"] |> String.trim_leading("$") |> String.to_float |> Kernel.*(100),
        isAvailable: item["isAvailable"]
      }
    end)
    |> IO.inspect
    

    输出:

    [%{color: "Black", isAvailable: true, price: 4.15e4, size: "11"},
     %{color: "Black", isAvailable: true, price: 4.15e4, size: "11"}]
    

答案 2 :(得分:0)

您遇到访问错误,因为如果thing.property是原子,您只能使用property语法,而在json地图中,键是字符串。

使这更容易的一件事是Poison.decode可以使用keys: :atoms的第二个参数来返回带有原子键的地图。使用这里的内容,这将解决问题:

json_atoms = Poison.encode!(json) |> Poison.decode!(keys: :atoms)
convert_price = fn x -> 
  String.trim_leading(x, "$")
  |> String.to_float
  |> &(&1 * 100)
  |> trunc
end

Enum.map(json_atoms, fn {_k,v} -> %{
  color: v.attributes.color,
  size: v.attributes.size,
  price: convert_price.(v.pricing.standard),
  isAvailable: v.isAvailable
} end)