質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

Q&A

2回答

4314閲覧

Google MapのJSONから住所を取得したい

nasama

総合スコア16

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

0グッド

1クリップ

投稿2017/05/25 12:48

C#を使用しています。郵便番号を入力すると住所を検索できるようにしたいと思っています。

https://maps.googleapis.com/maps/api/geocode/json?address=5150017&language=ja&sensor=false

{ "results" : [ { "address_components" : [ { "long_name" : "515-0017", "short_name" : "515-0017", "types" : [ "postal_code" ] }, { "long_name" : "京町", "short_name" : "京町", "types" : [ "political", "sublocality", "sublocality_level_1" ] }, { "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" : "〒515-0017, 日本", "geometry" : { "bounds" : { "northeast" : { "lat" : 34.5793157, "lng" : 136.5379723 }, "southwest" : { "lat" : 34.5718256, "lng" : 136.5339043 } }, "location" : { "lat" : 34.575748, "lng" : 136.5361218 }, "location_type" : "APPROXIMATE", "viewport" : { "northeast" : { "lat" : 34.5793157, "lng" : 136.5379723 }, "southwest" : { "lat" : 34.5718256, "lng" : 136.5339043 } } }, "place_id" : "ChIJU_uxoOBqBGARjIajaAPpsNM", "types" : [ "postal_code" ] } ], "status" : "OK" }

取得できるJSONのうち、住所の部分のみを取得したいです。
(上記の例でいえば、「京町」「松阪市」「三重県」のみ)

文字列を抽出しようと思いましたが、共通で後ろの項目が「long_name」「short_name」のため、うまく探すことができない状態です。
かといって、「三重県」だけを抽出するとほかの都道府県が表示されないので、どうしたら正確に検索できるかわからない状態です。
違いがあるとすれば"types"内のデータなので、ここから判別して個別に取得する形になるかとは思うのですが、どのように書いていったら良いかがわからないです。
どのようにしたら取得できるでしょうか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

JSON が適切なオブジェクトにマッピング済みであるなら、LINQ で

var address = jobject.results[0].address_components .Where(_ => _.types.Contains("political") && !_.types.Contains("country")) .Slect(_ => _.long_name);

のような感じで抽出出来るんじゃないでしょうか。

投稿2017/05/25 13:23

編集2017/05/25 13:50
hidori

総合スコア402

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nasama

2017/05/30 12:08

ありがとうございます。しかし「'string' に 'results' の定義が含まれておらず、型 'string' の最初の引数を受け付ける拡張メソッド 'results' が見つかりませんでした。using ディレクティブまたはアセンブリ参照が不足していないことを確認してください。」と表示されます。クイックアクションとリファクタリングをしても「results[0]」を削っても別のところでエラーが出てしまいます。
hidori

2017/05/30 13:07

>JSON が適切なオブジェクトにマッピング済みであるなら と注記した通りです。 Json.NET などを使って JSON を適切なオブジェクトにマッピングしてください。
guest

0

JSONから特定のフィールドを抽出することは、Jilなどの、JSONシリアライザを利用することでさほど難しくなく実現できます。

以下のサンプルコードは、GoogleのGeoCodeAPIの仕様を当たっていないので、いくつかクエリを投げて出てきた結果から類推しておりますので、その点ご了承ください。

特に、address_componetnsの出現序列に完全に依存していますから、その点は特にご留意の程。

また、先に紹介したJilを、Nugetなりで導入していることを前提としております。

また、C#7以降を想定しており、.NET Framework4.6以降が必要だと思います。

csharp

1using System; 2using System.Collections.Generic; 3using System.Linq; 4using System.Net.Http; 5using System.Threading.Tasks; 6using Jil; 7 8namespace Sample 9{ 10 internal class Program 11 { 12 private static void Main(string[] args) 13 { 14 //誤入力訂正は一切考えてないのでお察しくださいw 15 Console.WriteLine("〒番号は?"); 16 var input = Console.ReadLine(); 17 18 //ジオコードAPIに投げて貰ってくる。 19 var task = GetData(input); 20 var source = task.Result; 21 22 //Jilにてデシリアライズしつつ欲しい部分(address_components要素)を抜いてくる。 23 var datum = (IEnumerable<dynamic>) JSON.DeserializeDynamic(source).results[0].address_components; 24 25 //出現順序を記憶しつつ整形する。(タプル使ってる) 26 var addressComponents = 27 datum.Select((d, i) => (Order:i, Name:(string) d.long_name, Types:(IEnumerable<string>) d.types)); 28 29 //国名と〒番号の要素をフィルタ 30 var result = addressComponents.Where(x => !x.Types.Any(y => y == "country" || y == "postal_code")) 31 .OrderByDescending(x => x.Order); 32 33 //とりあえず名前だけ出力 34 foreach (var t in result) 35 Console.WriteLine(t.Name); 36 } 37 38 private static async Task<string> GetData(string postalCode) 39 { 40 using (var client = new HttpClient()) 41 { 42 var hoge = await client.GetAsync( 43 $"https://maps.googleapis.com/maps/api/geocode/json?address={postalCode.Trim('-')}&language=ja&sensor=false"); 44 45 var piyo = await hoge.Content.ReadAsStringAsync(); 46 47 return piyo; 48 } 49 } 50 } 51} 52

必要なアセンブリを参照させれば多分動くと思うので
後は適宜、ステップデバッグするなりして挙動を追っかけてみてください。

投稿2017/05/25 14:16

Tokeiya3

総合スコア260

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nasama

2017/05/30 12:21

ありがとうございます。早速Jilを導入しました。「名前 'Order' は、現在のコンテキストに存在しません。」「現在のコンテキストに 'Order' 'i' 'd' 'd' という名前は存在しません。」「foreach ステートメントは、'?' が 'GetEnumerator' のパブリック定義を含んでいないため、型 '?' の変数に対して使用できません。」とエラーが出ました。Mainのうえに「public static object Order { get; private set; }」を書くことで「Order」のエラーが取り除くことができましたが、ほかのエラーを治すことができませんでした。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問