japanese_address_parser 3.1.0 → 3.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -9,21 +9,51 @@ import {
9
9
  getCityRegexPatterns,
10
10
  getTownRegexPatterns,
11
11
  getSameNamedPrefectureCityRegexPatterns,
12
+ // interface version 1
12
13
  getResidentials,
13
14
  getGaikuList,
15
+ // interface version 2
16
+ getAddrs,
17
+ PrefectureList,
18
+ TownList,
19
+ AddrList,
14
20
  } from './lib/cacheRegexes'
15
21
  import unfetch from 'isomorphic-unfetch'
16
22
 
23
+ type TransformRequestResponse = null | PrefectureList | TownList | AddrList
24
+
25
+ export type TransformRequestQuery = {
26
+ level: number // level = -1 は旧 API。 transformRequestFunction を設定しても無視する
27
+ pref?: string
28
+ city?: string
29
+ town?: string
30
+ }
31
+
32
+ export type TransformRequestFunction = (
33
+ url: URL,
34
+ query: TransformRequestQuery,
35
+ ) => TransformRequestResponse | Promise<TransformRequestResponse>
36
+
17
37
  /**
18
38
  * normalize {@link Normalizer} の動作オプション。
19
39
  */
20
40
  export interface Config {
41
+ /**
42
+ * レスポンス型のバージョン。デフォルト 1
43
+ * 1 の場合は jyukyo: string, gaiku: string
44
+ * 2 の場合は addr: string, other: string
45
+ */
46
+ interfaceVersion: number
47
+
21
48
  /** 住所データを URL 形式で指定。 file:// 形式で指定するとローカルファイルを参照できます。 */
22
49
  japaneseAddressesApi: string
23
50
 
24
51
  /** 町丁目のデータを何件までキャッシュするか。デフォルト 1,000 */
25
52
  townCacheSize: number
26
53
 
54
+ /** 住所データへのリクエストを変形するオプション。 interfaceVersion === 2 で有効 */
55
+ transformRequest?: TransformRequestFunction
56
+
27
57
  geoloniaApiKey?: string
28
58
  }
29
59
  export const config: Config = currentConfig
@@ -31,7 +61,7 @@ export const config: Config = currentConfig
31
61
  /**
32
62
  * 住所の正規化結果として戻されるオブジェクト
33
63
  */
34
- export interface NormalizeResult {
64
+ interface NormalizeResult_v1 {
35
65
  /** 都道府県 */
36
66
  pref: string
37
67
  /** 市区町村 */
@@ -60,6 +90,34 @@ export interface NormalizeResult {
60
90
  level: number
61
91
  }
62
92
 
93
+ type NormalizeResult_v2 = {
94
+ /** 都道府県 */
95
+ pref: string
96
+ /** 市区町村 */
97
+ city: string
98
+ /** 町丁目 */
99
+ town: string
100
+ /** 住居表示または地番 */
101
+ addr: string
102
+ /** 正規化後の住所文字列 */
103
+ other?: string
104
+ /** 緯度。データが存在しない場合は null */
105
+ lat: number | null
106
+ /** 経度。データが存在しない場合は null */
107
+ lng: number | null
108
+ /**
109
+ * 住所文字列をどこまで判別できたかを表す正規化レベル
110
+ * - 0 - 都道府県も判別できなかった。
111
+ * - 1 - 都道府県まで判別できた。
112
+ * - 2 - 市区町村まで判別できた。
113
+ * - 3 - 町丁目まで判別できた。
114
+ * - 8 - 住居表示住所の街区符号・住居番号までの判別または地番住所の判別ができた。
115
+ */
116
+ level: number
117
+ }
118
+
119
+ export type NormalizeResult = NormalizeResult_v1 | NormalizeResult_v2
120
+
63
121
  /**
64
122
  * 正規化関数の {@link normalize} のオプション
65
123
  */
@@ -92,6 +150,7 @@ export type Normalizer = (
92
150
 
93
151
  export type FetchLike = (
94
152
  input: string,
153
+ requestQuery?: TransformRequestQuery,
95
154
  ) => Promise<Response | { json: () => Promise<unknown> }>
96
155
 
97
156
  const defaultOption = {
@@ -143,7 +202,13 @@ const normalizeResidentialPart = async (
143
202
  pref: string,
144
203
  city: string,
145
204
  town: string,
146
- ) => {
205
+ ): Promise<{
206
+ gaiku: string
207
+ jyukyo?: string
208
+ addr: string
209
+ lat: string
210
+ lng: string
211
+ } | null> => {
147
212
  const [gaikuListItem, residentials] = await Promise.all([
148
213
  getGaikuList(pref, city, town),
149
214
  getResidentials(pref, city, town),
@@ -183,6 +248,27 @@ const normalizeResidentialPart = async (
183
248
  return null
184
249
  }
185
250
 
251
+ const normalizeAddrPart = async (
252
+ addr: string,
253
+ pref: string,
254
+ city: string,
255
+ town: string,
256
+ ) => {
257
+ const addrListItem = await getAddrs(pref, city, town)
258
+
259
+ // 住居表示住所、および地番住所が見つからなかった
260
+ if (addrListItem.length === 0) {
261
+ return null
262
+ }
263
+
264
+ const addrItem = addrListItem.find((item) => addr.startsWith(item.addr))
265
+ if (addrItem) {
266
+ const other = addr.replace(addrItem.addr, '').trim()
267
+ return { addr: addrItem.addr, other, lat: addrItem.lat, lng: addrItem.lng }
268
+ }
269
+ return null
270
+ }
271
+
186
272
  export const normalize: Normalizer = async (
187
273
  address,
188
274
  _option = defaultOption,
@@ -378,7 +464,7 @@ export const normalize: Normalizer = async (
378
464
  // `-1` のようなケース
379
465
  return kan2num(s)
380
466
  })
381
- .replace(/-[^0-9]+([0-9〇一二三四五六七八九十百千]+)/, (s) => {
467
+ .replace(/-[^0-9]([0-9〇一二三四五六七八九十百千]+)/, (s) => {
382
468
  // `-あ1` のようなケース
383
469
  return kan2num(zen2han(s))
384
470
  })
@@ -392,43 +478,85 @@ export const normalize: Normalizer = async (
392
478
 
393
479
  addr = patchAddr(pref, city, town, addr)
394
480
 
395
- // 住居表示住所リストを使い番地号までの正規化を行う
396
- if (option.level > 3 && normalized && town) {
397
- normalized = await normalizeResidentialPart(addr, pref, city, town)
398
- }
399
- if (normalized) {
400
- lat = parseFloat(normalized.lat)
401
- lng = parseFloat(normalized.lng)
402
- }
403
-
404
- if (Number.isNaN(lat) || Number.isNaN(lng)) {
405
- lat = null
406
- lng = null
407
- }
408
-
409
481
  if (pref) level = level + 1
410
482
  if (city) level = level + 1
411
483
  if (town) level = level + 1
412
484
 
413
- const result: NormalizeResult = {
414
- pref,
415
- city,
416
- town,
417
- addr,
418
- lat,
419
- lng,
420
- level,
485
+ if (option.level <= 3 || level < 3) {
486
+ return { pref, city, town, addr, level, lat, lng }
421
487
  }
422
488
 
423
- if (normalized && 'gaiku' in normalized) {
424
- result.addr = normalized.addr
425
- result.gaiku = normalized.gaiku
426
- result.level = 7
427
- }
428
- if (normalized && 'jyukyo' in normalized) {
429
- result.jyukyo = normalized.jyukyo
430
- result.level = 8
431
- }
489
+ // ======================== Advanced section ========================
490
+ // これ以下は地番住所または住居表示住所までの正規化・ジオコーディングを行う処理
491
+ // 現状、インターフェース v1 と v2 が存在する
492
+ // japanese-addresses のフォーマット、および normalize 関数の戻り値が異なる
493
+ // 将来的に v2 に統一することを検討中
494
+ // ==================================================================
495
+
496
+ // v2 のインターフェース
497
+ if (currentConfig.interfaceVersion === 2) {
498
+ const normalizedAddrPart = await normalizeAddrPart(addr, pref, city, town)
499
+ let other = undefined
500
+ if (normalizedAddrPart) {
501
+ addr = normalizedAddrPart.addr
502
+ if (normalizedAddrPart.other) {
503
+ other = normalizedAddrPart.other
504
+ }
505
+ if (normalizedAddrPart.lat !== null)
506
+ lat = parseFloat(normalizedAddrPart.lat)
507
+ if (normalizedAddrPart.lng !== null)
508
+ lng = parseFloat(normalizedAddrPart.lng)
509
+ level = 8
510
+ }
511
+ const result: NormalizeResult_v2 = {
512
+ pref,
513
+ city,
514
+ town,
515
+ addr,
516
+ level,
517
+ lat,
518
+ lng,
519
+ }
520
+ if (other) {
521
+ result.other = other
522
+ }
523
+ return result
524
+ } else if (currentConfig.interfaceVersion === 1) {
525
+ // 住居表示住所リストを使い番地号までの正規化を行う
526
+ if (option.level > 3 && normalized && town) {
527
+ normalized = await normalizeResidentialPart(addr, pref, city, town)
528
+ }
529
+ if (normalized) {
530
+ lat = parseFloat(normalized.lat)
531
+ lng = parseFloat(normalized.lng)
532
+ }
533
+
534
+ if (Number.isNaN(lat) || Number.isNaN(lng)) {
535
+ lat = null
536
+ lng = null
537
+ }
538
+
539
+ const result: NormalizeResult_v1 = {
540
+ pref,
541
+ city,
542
+ town,
543
+ addr,
544
+ lat,
545
+ lng,
546
+ level,
547
+ }
548
+ if (normalized && 'gaiku' in normalized) {
549
+ result.addr = normalized.addr
550
+ result.gaiku = normalized.gaiku
551
+ result.level = 7
552
+ }
553
+ if (normalized && 'jyukyo' in normalized) {
554
+ result.jyukyo = normalized.jyukyo
555
+ result.level = 8
556
+ }
432
557
 
433
- return result
558
+ return result
559
+ } else {
560
+ throw new Error('invalid interfaceVersion')
561
+ }
434
562
  }
data/js/package-lock.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "": {
7
7
  "name": "japanese_address_parser",
8
8
  "dependencies": {
9
- "@geolonia/normalize-japanese-addresses": "^2.8.0"
9
+ "@geolonia/normalize-japanese-addresses": "^2.9.2"
10
10
  },
11
11
  "devDependencies": {}
12
12
  },
@@ -16,9 +16,9 @@
16
16
  "integrity": "sha512-xzSsIHhyyjqNpW8qSh5bFMu3FJvyJGBbNZ/t8clPHkigjUdZ7Ck8wkzCkcwlVd00RkoHwGDLnvXx5W0WiGK0TQ=="
17
17
  },
18
18
  "node_modules/@geolonia/normalize-japanese-addresses": {
19
- "version": "2.8.0",
20
- "resolved": "https://registry.npmjs.org/@geolonia/normalize-japanese-addresses/-/normalize-japanese-addresses-2.8.0.tgz",
21
- "integrity": "sha512-BNKTl+38nq+ZKABa9nmwixLyDTXDPYDWSG3DluTjvhog3LEVWcTOHy0taIWXpumlvoz67ingq2qxdjtvW8ktzQ==",
19
+ "version": "2.9.2",
20
+ "resolved": "https://registry.npmjs.org/@geolonia/normalize-japanese-addresses/-/normalize-japanese-addresses-2.9.2.tgz",
21
+ "integrity": "sha512-sbeV/seJ/ue6pn2sLo+Ccunl6eB3yNhrUIzNpT2IiR9Fw6fW5f1lLdApODqhTmz++xr1dyPwZOzTXCGEaXejDA==",
22
22
  "dependencies": {
23
23
  "@geolonia/japanese-numeral": "^0.1.16",
24
24
  "isomorphic-unfetch": "^3.1.0",
@@ -101,9 +101,9 @@
101
101
  "integrity": "sha512-xzSsIHhyyjqNpW8qSh5bFMu3FJvyJGBbNZ/t8clPHkigjUdZ7Ck8wkzCkcwlVd00RkoHwGDLnvXx5W0WiGK0TQ=="
102
102
  },
103
103
  "@geolonia/normalize-japanese-addresses": {
104
- "version": "2.8.0",
105
- "resolved": "https://registry.npmjs.org/@geolonia/normalize-japanese-addresses/-/normalize-japanese-addresses-2.8.0.tgz",
106
- "integrity": "sha512-BNKTl+38nq+ZKABa9nmwixLyDTXDPYDWSG3DluTjvhog3LEVWcTOHy0taIWXpumlvoz67ingq2qxdjtvW8ktzQ==",
104
+ "version": "2.9.2",
105
+ "resolved": "https://registry.npmjs.org/@geolonia/normalize-japanese-addresses/-/normalize-japanese-addresses-2.9.2.tgz",
106
+ "integrity": "sha512-sbeV/seJ/ue6pn2sLo+Ccunl6eB3yNhrUIzNpT2IiR9Fw6fW5f1lLdApODqhTmz++xr1dyPwZOzTXCGEaXejDA==",
107
107
  "requires": {
108
108
  "@geolonia/japanese-numeral": "^0.1.16",
109
109
  "isomorphic-unfetch": "^3.1.0",
data/js/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "private": true,
4
4
  "description": "JapaneseAddressParserは日本の住所をパースすることができるRuby gemです。",
5
5
  "dependencies": {
6
- "@geolonia/normalize-japanese-addresses": "^2.8.0"
6
+ "@geolonia/normalize-japanese-addresses": "^2.9.2"
7
7
  },
8
8
  "devDependencies": {}
9
9
  }
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module JapaneseAddressParser
4
- VERSION = '3.1.0'
4
+ VERSION = '3.1.1'
5
5
  public_constant :VERSION
6
6
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: japanese_address_parser
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.0
4
+ version: 3.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yamaguchi Takuya
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-07-24 00:00:00.000000000 Z
11
+ date: 2023-09-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: schmooze
@@ -4160,7 +4160,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
4160
4160
  - !ruby/object:Gem::Version
4161
4161
  version: '0'
4162
4162
  requirements: []
4163
- rubygems_version: 3.4.1
4163
+ rubygems_version: 3.4.18
4164
4164
  signing_key:
4165
4165
  specification_version: 4
4166
4166
  summary: Japanese address parser written in Ruby.