在 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)
但是这段代码给出了一些与访问相关的错误。
三件事:
你有一张地图,所以 Enum.map
会给你一个键和值的元组。你只想要这里的值,所以这样做:
fn {_, item} ->
地图中的键是字符串。点语法仅适用于原子键。你需要做的:
item["attributes"]
而不是
item.attributes
其他键也类似。
你的价格是一个字符串。您需要先将其转换为 Float,然后才能将其相乘。您可以使用 String.trim_leading
和 String.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)
我使用 Posion.decode!
解析了以下 JSONjson = %{"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)
但是这段代码给出了一些与访问相关的错误。
三件事:
你有一张地图,所以
Enum.map
会给你一个键和值的元组。你只想要这里的值,所以这样做:fn {_, item} ->
地图中的键是字符串。点语法仅适用于原子键。你需要做的:
item["attributes"]
而不是
item.attributes
其他键也类似。
你的价格是一个字符串。您需要先将其转换为 Float,然后才能将其相乘。您可以使用
这样做String.trim_leading
和String.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)