mochijson2
Erlang で JSON からデータを取り出したくて、mochijson2 に辿り着いた。
https://github.com/bjnortier/mochijson2
やりたかったことは、Google Geocoding APIを使って、住所から座標を取り出すこと。
説明に書いてあるとおり、
http://maps.googleapis.com/maps/api/geocode/json?address=東京都新宿区
のように検索すると、結果が JSON 形式で返ってくる。
{ "results" : [ { "address_components" : [ { "long_name" : "新宿区", "short_name" : "新宿区", "types" : [ "locality", "political" ] }, { "long_name" : "東京都", "short_name" : "東京都", "types" : [ "administrative_area_level_1", "political" ] }, { "long_name" : "日本", "short_name" : "JP", "types" : [ "country", "political" ] } ], "formatted_address" : "日本, 東京都新宿区", "geometry" : { "bounds" : { "northeast" : { "lat" : 35.7298939, "lng" : 139.7451615 }, "southwest" : { "lat" : 35.6731516, "lng" : 139.6732487 } }, "location" : { "lat" : 35.6938401, "lng" : 139.7035494 }, "location_type" : "APPROXIMATE", "viewport" : { "northeast" : { "lat" : 35.7298939, "lng" : 139.7451615 }, "southwest" : { "lat" : 35.6731516, "lng" : 139.6732487 } } }, "types" : [ "locality", "political" ] } ], "status" : "OK" }
この結果が 下記コードの Body に入っている。
構造としては、
1. results の中の配列の一番目の塊の中
2. geometry というキーのバリューの中
3. location というキーのバリューの中
4. lat, lng というキーの値がそれぞれ緯度経度
これを順に辿っていくことになる。
Decoded = mochijson2:decode(Body), {struct, Results} = Decoded, Results2 = proplists:get_value(< <"results">>, Results), [H, T] = Results2, {struct, Items} = H, Geo = proplists:get_value(< <"geometry">>, Items), {struct, Locs} = Geo, Loc = proplists:get_value(< <"location">>, Locs), {struct, Latng} = Loc, Lat = proplists:get_value(< <"lat">>, Latng), Lng = proplists:get_value(< <"lng">>, Latng),
ポイントとしては、
・mochijson2:decode から値を取り出すと {struct, 本体} という形なので、本体のほうを分解していく
・キーの名前を指定するときは、バイナリ形式で < <"キー">> という形で書く
・配列の先頭を取り出すときに [H, T] という形に代入すると H が先頭(Head)
といったところだったかな。
参考になったサイトは、
Destructuring JSON in Erlang Made Easy
である。
最初にコマンドラインでちゃんと分解してみてから、アプリのコードに組み込むべし。
このあと住所の投げ方によって返ってくる形が違うことがわかり、If文とかを追加してちょっと複雑になった。
そんなこんな、誰が使うんだろうね・・・
Erlang が流行ってるのかどうか、全然知らない。