%{"attributes" => %{"color" => "Black"...">

JSON Map in Elixir

I parsed the following JSON using Posion.decode!

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

I want to map this, and I cannot get the JSON elements as text in the node element. So far I have tried.

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

But this code gives some access related error.

+4
source share
3 answers

When matching a map, repeating key-value pairs arrive in mapper as tuples {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"}
# ]

Here we use inplace pattern matching for values โ€‹โ€‹in mapper to simplify the pairing code itself and make it less error prone in case of bad input.

+4
source

Three things:

  • You have a map, so it Enum.mapwill give you a set of keys and values. You just need the value here, so:

    fn {_, item} ->
    
  • . . :

    item["attributes"]
    

    item.attributes
    

    .

  • . Float, . , String.trim_leading String.to_float:

    iex(1)> "$123.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"}]
+2

You get access errors because you can use the syntax thing.propertyif it propertyis an atom and there are lines on your json card.

One thing that will make this a lot easier is that it Poison.decodecan take a second argument keys: :atomsto return a map with atomic keys. Working with what you have here, this will solve the problem:

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)
0
source

Source: https://habr.com/ru/post/1689434/


All Articles