Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Map JSON values in Elixir

I have 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'm unable to get JSON elements as the text in the node element changes. So far I've 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 error related to accessing.

like image 778
RN92 Avatar asked Mar 07 '23 13:03

RN92


2 Answers

While mapping the map, the iterated key-value pairs come to the 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 an inplace pattern matching for values in mapper to simplify the code of matcher itself and make it less error-prone in a case of bad input.

like image 188
Aleksei Matiushkin Avatar answered Apr 08 '23 03:04

Aleksei Matiushkin


Three things:

  1. You have a map so Enum.map will give you a tuple of key and value. You just want the value here, so do:

    fn {_, item} ->
    
  2. The keys in your map are strings. The dot syntax only works for atom keys. You need to do:

    item["attributes"]
    

    instead of

    item.attributes
    

    and similar for other keys.

  3. The price you have is a string. You'll need to convert it to a Float before you can multiply it. You can do it like this using String.trim_leading and 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

Output:

[%{color: "Black", isAvailable: true, price: 4.15e4, size: "11"},
 %{color: "Black", isAvailable: true, price: 4.15e4, size: "11"}]
like image 42
Dogbert Avatar answered Apr 08 '23 04:04

Dogbert