在 Elixir 中映射 JSON 个值

Map JSON values in Elixir

我使用 Posion.decode!

解析了以下 JSON
json = %{"color-Black|size:10" => 
    %{"attributes" => %{"color" => "Black","size" => "11"},    
      "isAvailable" => true,      
    "pricing" => %{"standard" => "5.00", "sale" => 415}}, 
 "color|size-EU:9.5" => 
    %{"attributes" => %{"color" => "Black","size" => "11"},    
      "isAvailable" => true,      
    "pricing" => %{"standard" => "5.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)

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

三件事:

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

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

    item["attributes"]
    

    而不是

    item.attributes
    

    其他键也类似。

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

    这样做
    iex(1)> "3.45" |> String.trim_leading("$") |> String.to_float
    123.45
    

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

映射映射时,迭代的键值对作为元组进入映射器{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: "5.00", size: "11"},
#    %{color: "Black", isAvailable: true, price: "5.00", size: "11"}
# ]

这里我们对mapper中的值使用inplace pattern matching来简化matcher本身的代码,并且在错误输入的情况下更不容易出错。

您收到访问错误,因为如果 property 是一个原子并且在您的 json 映射中,键是字符串,您只能使用 thing.property 语法。

使这更容易的一件事是 Poison.decode 可以将 keys: :atoms 的第二个参数带到 return 具有原子键的映射。使用这里的内容,这将解决问题:

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)