Google geocoding APIを試し結果を得る

Google geocoding API でキーワードをもとに緯度経度・住所を取得できる。事前準備・手続きから試用して結果XMLを取得するまでを解説した。

無料枠で使ってみるまでに必要な手続き

  • Googleアカウントを作っておく
  • https://console.cloud.google.com/getting-started にアクセスし、『有効なAPIとサービス』メニューからGeocoding APIを探し有効化
  • https://console.cloud.google.com/billing で請求先アカウントを追加しておく
  • https://console.cloud.google.com/apis/credentials でAPIキーを作成しておく(XXXXとする)

アクセスを試す

以下URLにアクセスし、結果に示すような画面出力を得られるのを確認する

https://www.google.co.jp/maps/api/geocode/xml?address=skytree&sensor=true&key=XXXX

※addressの値は検索キーワード、keyの値は作成したAPIキーに適宜変更すること

結果

<GeocodeResponse>
	<status>OK</status>
	<result>
		<type>establishment</type>
		<type>point_of_interest</type>
		<type>tourist_attraction</type>
		<formatted_address>日本、〒131-0045 東京都墨田区押上1丁目1−2</formatted_address>
		<address_component>
			<long_name>2</long_name>
			<short_name>2</short_name>
			<type>premise</type>
		</address_component>
		<address_component>
			<long_name>1</long_name>
			<short_name>1</short_name>
			<type>political</type>
			<type>sublocality</type>
			<type>sublocality_level_4</type>
		</address_component>
		<address_component>
			<long_name>1丁目</long_name>
			<short_name>1丁目</short_name>
			<type>political</type>
			<type>sublocality</type>
			<type>sublocality_level_3</type>
		</address_component>
		<address_component>
			<long_name>押上</long_name>
			<short_name>押上</short_name>
			<type>political</type>
			<type>sublocality</type>
			<type>sublocality_level_2</type>
		</address_component>
		<address_component>
			<long_name>墨田区</long_name>
			<short_name>墨田区</short_name>
			<type>locality</type>
			<type>political</type>
		</address_component>
		<address_component>
			<long_name>東京都</long_name>
			<short_name>東京都</short_name>
			<type>administrative_area_level_1</type>
			<type>political</type>
		</address_component>
		<address_component>
			<long_name>日本</long_name>
			<short_name>JP</short_name>
			<type>country</type>
			<type>political</type>
		</address_component>
		<address_component>
			<long_name>131-0045</long_name>
			<short_name>131-0045</short_name>
			<type>postal_code</type>
		</address_component>
		<geometry>
			<location>
				<lat>35.7100627</lat>
				<lng>139.8107004</lng>
			</location>
			<location_type>ROOFTOP</location_type>
			<viewport>
				<southwest>
					<lat>35.7089225</lat>
					<lng>139.8084778</lng>
				</southwest>
				<northeast>
					<lat>35.7116204</lat>
					<lng>139.8132971</lng>
				</northeast>
			</viewport>
		</geometry>
		<partial_match>true</partial_match>
		<place_id>ChIJ35ov0dCOGGARKvdDH7NPHX0</place_id>
		<plus_code>
			<global_code>8Q7XPR66+27</global_code>
			<compound_code>PR66+27 東京都墨田区</compound_code>
		</plus_code>
	</result>
</GeocodeResponse>

所感

知らない人が試すには手続きで時間がかかる。けれど、ブラウザのGETメソッドで簡単にデータを取得できるから物凄く手軽。

無料枠でもいろいろ試せる&楽しめたから、いろんな人に試してほしい機能だ。

VB .NET で複雑にネストされたJSONデータを取り扱う

Visual Basic .NETでJSONデータを取り扱うのにJson .NETが便利。JSON文字列データをDeserialize時の格納クラスを円滑に定義するための備忘録である。

※Json .NET:NuGet上パッケージ名は NewtonSoft.Json

課題

Json .NET を用いると、以下コードのようにSourceのJSON文字列をMyClassの形式に格納出来る。

Dim StructuredData = JsonConvert.DeserializeObject(Of MyClass)(source)

しかしこのMyClassをどう定義するかが初心者には難しい。

もっと具体的に言えば、YouTube Data API V3のデータを取り扱おうと思っても、入れ子にされたデータに対してどうクラスを定義すればStructuredDataに格納できるかに悩む。複雑なデータをお手軽快適に取り扱うのが課題だった。

結論

直下のデータ

基本的なデータの取り扱い

配列ではない個別項目にアクセスしたい場合はそれぞれプロパティを定義する。つまり、以下例であればPublic Property kind As String と定義し Debug.Print (StructuredData.kind) という形で使える。

{
__”kind”: “youtube#playlistItemListResponse”,
__”etag”: “XXX_XXXXXXXXXXXXX_X-XXXXXXX”,
__”nextPageToken”: “XXXXXXXXXXXXXX”,

Public Class MyClass
__Public Property kind As String
__Public Property etag As String
__Public Property nextPageToken As String
End Class

同じ階層の全データが同じデータ型のKey-Valueの形になっている場合

以下 pageInfo 項目内、totalResults, resultsPerPage は両方とも String – Long 構成とみなせる。

{
__”kind”: “youtube#playlistItemListResponse”,
__”etag”: “XXX_XXXXXXXXXXXXX_X-XXXXXXX”,
__”pageInfo”: {
____”totalResults”: 11,
____”resultsPerPage”: 10
__}
}

この場合はPublic Property kv As Dictionary(Of DataTypeKey, DataTypeValue) の形で定義すればDebug.Print (kv(“kind”))のように必要項目のみKEY指定して扱える。

Public Class MyClass
__Public Property pageInfo As Dictionary(Of String, Long)
End Class

更に下の階層のデータを持つ項目がある場合・データ型が異なる場合

Public Class MyClass
__Public Property kind As String
__Public Property etag As String
__Public Property pageInfo As Dictionary(Of String, Long)
End Class

個別にプロパティを設けて厳密にアクセスしたい場合は個別に項目を定義する。つまり、Public Property kind As String と定義し Debug.Print (StructuredData.kind) という形で使える。

配列データ

変数名の右に [ 記号でくくってある場合は配列データである。

.NET で規定されている型のデータが配列になっている場合

以下構成であれば Public Property name As List(Of String) で定義すれば良い。 ※YouTubeAPI出力になかったので動作未確認。

__”name”: [
____”AAA”,
____”BBB”
__],

Public Class MyClass
__Public Property name As List(Of String)
End Class

.NET で規定されていない型のデータが配列になっている場合

対象の配列(下の例であればitems, snippet)それぞれをまるまるクラスとして定義し、上述の応用で配列のやり方(Public Property items As List(Of NestedClass), Public Property snippet As NestedNestedClass)で配列項目または個別項目と決めればよい。

{
__”kind”: “youtube#playlistItemListResponse”,
__”etag”: “XXX_XXXXXXXXXXXXX_X-XXXXXXX”,
__”nextPageToken”: “XXXXXXXXXXXXXX”,
__”items”: [
____{
______”kind”: “youtube#playlistItem”,
______”etag”: “XXXXXXXXXXXXXXXXXXXX_XXXXXX”,
______”id”: “XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX”,
______”snippet”: {
________”publishedAt”: “2022-02-20T17:23:00Z”,
________”resourceId”: {
__________”kind”: “youtube#video”,
__________”videoId”: “XXXXXXXXXXX”
________},

Public Class MyClass
__Public Property kind As String
__Public Property etag As String
__Public Property nextPageToken As String
__Public Property items As List(Of NestedClass)
End Class

Public Class NestedClass
__Public Property kind As String
__Public Property etag As String
__Public Property id As String
__Public Property snippet As NestedNestedClass
End Class

Public Class NestedNestedClass
__Public Property publishedAt As Date
__Public Property resourceId As Dictionary(Of String, String)
End Class

調査実施環境:

  • Windows 11
  • Visual Studio .NET 2019
  • .NET Core 3.1
  • Json .NET .NET Standard 2.0 Version 13.0.1.25517

Openldap再起動に失敗した復旧試行錯誤

dockerコンテナ osixia/openldap を使っていたが、コンテナを再起動したら即落ちで正常起動しなくなった不具合調査と対応結果。

状況

docker ps -a で見ても EXITED となる。表示されるログは以下の通り。

[root@hoge ~]# docker logs openldap
*** CONTAINER_LOG_LEVEL = 3 (info)
*** Copy /container/service to /container/run/service
*** Search service in CONTAINER_SERVICE_DIR = /container/run/service :
*** link /container/run/service/:ssl-tools/startup.sh to /container/run/startup/:ssl-tools
*** link /container/run/service/slapd/startup.sh to /container/run/startup/slapd
*** link /container/run/service/slapd/process.sh to /container/run/process/slapd/run
*** Set environment for startup files
*** Environment files will be proccessed in this order :
Caution: previously defined variables will not be overriden.
/container/environment/99-default/default.yaml
/container/environment/99-default/default.startup.yaml
~中略~
TLS: could not use CA certificate file `/container/run/service/slapd/assets/certs/ca.crt': Error while reading file. (-64)
61909a9b main: TLS init def ctx failed: -1
61909a9b slapd stopped.
61909a9b connections_destroy: nothing to destroy.
*** /container/run/process/slapd/run exited with status 1
*** Killing all processes...

結論

結論としては問題は3つあった。

  • 設定の上書きを禁止していた
  • TLSを無効化していなかった ※実際に使っているなら残して良い。使っていないのに無効化してなかった
  • 何故かよくわからないがdockerのパラメータHOSTNAMEの扱いに何か変更があった様子

対策

以下の docker パラメータ修正で立ち上がるようになった。

追加

LDAP_TLS: "false"

削除

HOSTNAME: "example.com"
KEEP_EXISTING_CONFIG: "true"

調査経緯

読めぬなら読ませて見せよう…ということで、 /container/run/service/slapd/assets/certs/ca.crt を配置してみた。

するとca.crt以外にも公開鍵・秘密鍵・DHPARAMも不足している旨のエラーが順に表示されたのでそれらも足した。

でもそもそも内部用でTLSは使っていないから LDAP_TLS : “false”を足した。けれど直らなかった。

よくよく警告文言を見ると定義済み変数は上書きされないと書いてあったから KEEP_EXISTING_CONFIG: “true” を消した。そして docker logs openldap のエラー文言部分が以下に変わった。

61a19a26 slapd starting
61a19a26 daemon: listen(ldap://516808931dce:389, 5) failed errno=98 (Address already in use)
61a19a26 slapd stopped.
*** INFO | 2021-11-27 02:38:30 | /container/run/process/slapd/run exited with status 0
*** INFO | 2021-11-27 02:38:30 | Killing all processes…

このサーバー自体での問題だから、Address already in use はコンテナ内部の問題。

この辺の文言でググっていたところ、HOSTNAMEが怪しいぞという話があった。何か故あってHOSTNAMEのパラメータは消すべきとなった様子だが具体的な理由が知りたいわけではないからよしとする。

docker 起動パラメータから消したら正常表示されるようになった。