Parsing api returned list

I’m trying to parse a nested list returned by an API and coming up a bit empty.

The data returned:

%{"data" => [%{"custom_field_id" => 5, "custom_field_name" => "router_ssid",
"data" => "routerSSID"},
%{"custom_field_id" => 6, "custom_field_name" => "router_key",
"data" => "routerKey"}],
"paginator" => %{"current_page" => 1, "limit" => 100, "total_count" => 2,
"total_pages" => 1}}

Essentially I want to be able to get the value “routerKey” by looking for “router_key”. I could probably get this done through entirely too many complicated steps, but was wondering what the best practices are for parsing this kind of response.

Did you got that as an ASCII response? It looks as if it were already an elixir map… If though this was once JSON and you have converted it already, then you do not need to parse anymore, but to extract.

So as I’ve understood you, you want to iterate the list and convert them in a way, that the value of "custom_field_name" is a new key and the value of "data" then is the value.

To extract the info as described by me from a single Item in the list, just do the following:

def extract(%{"custom_field_name" => key, "data" => value}), do: {key, value}
def extract(_), do: nil

And now, jast map and perhaps filter nils…

You’ll get a tuple with the “key” as first and the “data” as second element.

If this is not what you want, please give more detail about how you want to look the transformed data like…

Given your map from above is input and the transformation funtion is called foo, what do you expect foo(input) to return (in elixir terms)?

Sorry for the confusion. The map above is what I’ve already parsed from the JSON response. You’re correct in what I’m expecting.

I’m looking to extract it to something like this:

%{"router_ssid" => "routerSSID",
"router_key" => "routerKey"}

Yeah, then just map my function over your input list, filter out the nils and then Enum.into(%{}), that should do it.

Enum.into(raw_result["data"], %{}, fn %{"custom_field_name" => name, "data" => value} -> {name, value} end)
1 Like

Wow, thanks Greg! I’m local as well in Dallas.

1 Like

Didn’t realize that there is a form of Enum.into that takes a function. I really need to remember this! Thank you!

I find for more readable personally:

╰─➤  iex                                                                                                         [9/131]
Erlang/OTP 20 [erts-9.0] [source] [64-bit] [smp:2:2] [ds:2:2:10] [async-threads:10] [hipe] [kernel-poll:false]

Interactive Elixir (1.6.0-dev) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> blah = %{"data" => [%{"custom_field_id" => 5, "custom_field_name" => "router_ssid",
...(1)> "data" => "routerSSID"},
...(1)> %{"custom_field_id" => 6, "custom_field_name" => "router_key",
...(1)> "data" => "routerKey"}],
...(1)> "paginator" => %{"current_page" => 1, "limit" => 100, "total_count" => 2,
...(1)> "total_pages" => 1}}
%{
  "data" => [%{
     "custom_field_id" => 5,
     "custom_field_name" => "router_ssid",
     "data" => "routerSSID"
   },
   %{
     "custom_field_id" => 6,
     "custom_field_name" => "router_key",
     "data" => "routerKey"
   }],
  "paginator" => %{
    "current_page" => 1,
    "limit" => 100,
    "total_count" => 2,
    "total_pages" => 1
  }
}
iex(2)> for %{"custom_field_name" => name, "data" => data} <- blah["data"], into: %{}, do: {name, data}
%{"router_key" => "routerKey", "router_ssid" => "routerSSID"}

Though I really hate the ant turd commas of it. ^.^;

Thanks for that. After posting I started thinking about a for comprehension. There’s also a benefit besides style. If one of the map entries is missing one of the keys, the Enum.into approach will give a match error, but for will ignore them.

I vote for the for solution.

1 Like