Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to work with nested data structures in Elixir

Tags:

elixir

I'm trying to work with the Google Maps geocoding API in Elixir though I'm a bit new to the language so working with nested data structures is eluding me.

I'm using HTTPotion to fetch the JSON from the geocoding endpoint and parsing it into Elixir data structures (a series of nested lists and tuples) using JSEX.

defmodule Geocode do
  def fetch do
    HTTPotion.start
    result = HTTPotion.get "http://maps.googleapis.com/maps/api/geocode/json?address=Fairfax,%20Vermont&sensor=false"
    json   = JSEX.decode result.body
  end
end

The following is now assigned to json.

{:ok, [{"results", [[{"address_components", [[{"long_name", "Fairfax"}, {"short_name", "Fairfax"}, {"types", ["locality", "political"]}], [{"long_name", "Franklin"}, {"short_name", "Franklin"}, {"types", ["administrative_area_level_2", "political"]}], [{"long_name", "Vermont"}, {"short_name", "VT"}, {"types", ["administrative_area_level_1", "political"]}], [{"long_name", "United States"}, {"short_name", "US"}, {"types", ["country", "political"]}]]}, {"formatted_address", "Fairfax, VT, USA"}, {"geometry", [{"bounds", [{"northeast", [{"lat", 44.772892}, {"lng", -72.92268890000001}]}, {"southwest", [{"lat", 44.6330508}, {"lng", -73.08477409999999}]}]}, {"location", [{"lat", 44.6654963}, {"lng", -73.01032}]}, {"location_type", "APPROXIMATE"}, {"viewport", [{"northeast", [{"lat", 44.772892}, {"lng", -72.92268890000001}]}, {"southwest", [{"lat", 44.6330508}, {"lng", -73.08477409999999}]}]}]}, {"types", ["locality", "political"]}]]}, {"status", "OK"}]}

I'd like to extract the latitude and the longitude from this nested data structure. I've tried using pattern matching but as the structure is fairly complex the corresponding pattern is a bit of a nightmare. While the following works it can't possibly be a good solution.

{_, [{_, [[_, _, { _, [{_, [{_, [{_, lat}, {_, lgn}]}, _]}, _, _, _] }, _]]}, _]} = json

So my question is what is the best way to extract values from deeply nested data structures in Elixir? Any solutions or nudges in the right direction would be greatly appreciated.

like image 532
Tristan O'Neil Avatar asked Dec 08 '22 13:12

Tristan O'Neil


2 Answers

Check out the source to Seth Falcon's ej library:

https://github.com/seth/ej

It does more or less what you're wanting to do, using recursion.

I'm not an Elixir expert, but you might be able to just use that library directly.

like image 165
Josh Black Avatar answered Dec 17 '22 18:12

Josh Black


The ej library looks like a good choice, but in addition I might cut to the heart of the data structure right away:

{:ok, [{"results", results}, {"status", status}]} = JSEX.decode result.body

or if you will always only use the first result:

{:ok, [{"results", [geo_json | _]}, {"status", status}]} = JSEX.decode result.body

Then I would use the ej library on the geo_json data structure.

like image 37
Alan Peabody Avatar answered Dec 17 '22 19:12

Alan Peabody