diff --git a/CHANGELOG.md b/CHANGELOG.md index e20e5374e..18cb4ca58 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ Guide: https://keepachangelog.com/en/1.0.0/ +- [Discover] Add support for country, proximity, and origin parameters in Discover.Options search parameters. This fixes an issue when using search-along-route to query category results. + - [SearchUI] Add `distanceFormatter` field to Configuration to support changing the search suggestions distance format. Nil values will use the default behavior. - [Core] Add xcprivacy for MapboxSearch and MapboxSearchUI diff --git a/MapboxSearch.xcodeproj/project.pbxproj b/MapboxSearch.xcodeproj/project.pbxproj index 55a8aeade..487cd7d9f 100644 --- a/MapboxSearch.xcodeproj/project.pbxproj +++ b/MapboxSearch.xcodeproj/project.pbxproj @@ -12,6 +12,10 @@ 042477C62B72CCB000D870D5 /* geocoding-reverse-geocoding.json in Resources */ = {isa = PBXBuildFile; fileRef = 042477C42B72CCB000D870D5 /* geocoding-reverse-geocoding.json */; }; 042477C72B72CCB000D870D5 /* geocoding-reverse-geocoding.json in Resources */ = {isa = PBXBuildFile; fileRef = 042477C42B72CCB000D870D5 /* geocoding-reverse-geocoding.json */; }; 043A3D4D2B30F38300DB681B /* CoreAddress+AddressComponents.swift in Sources */ = {isa = PBXBuildFile; fileRef = 043A3D4C2B30F38300DB681B /* CoreAddress+AddressComponents.swift */; }; + 048823482B6B0A9D00C770AA /* category-hotel-search-along-route-jp.json in Resources */ = {isa = PBXBuildFile; fileRef = 04AB0B7C2B6B043C00FDE7D5 /* category-hotel-search-along-route-jp.json */; }; + 048823492B6B0A9D00C770AA /* category-hotel-search-along-route-jp.json in Resources */ = {isa = PBXBuildFile; fileRef = 04AB0B7C2B6B043C00FDE7D5 /* category-hotel-search-along-route-jp.json */; }; + 0488234A2B6B0A9E00C770AA /* category-hotel-search-along-route-jp.json in Resources */ = {isa = PBXBuildFile; fileRef = 04AB0B7C2B6B043C00FDE7D5 /* category-hotel-search-along-route-jp.json */; }; + 04AB0B7B2B6AF43E00FDE7D5 /* DiscoverIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04AB0B792B6AF37800FDE7D5 /* DiscoverIntegrationTests.swift */; }; 04970F8D2B7A97C900213763 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 04970F8C2B7A97C900213763 /* PrivacyInfo.xcprivacy */; }; 04AB0B4B2B6AADB700FDE7D5 /* mapbox.places.san.francisco.json in Resources */ = {isa = PBXBuildFile; fileRef = 04AB0B4A2B6AADB700FDE7D5 /* mapbox.places.san.francisco.json */; }; 04AB0B4C2B6AADB700FDE7D5 /* mapbox.places.san.francisco.json in Resources */ = {isa = PBXBuildFile; fileRef = 04AB0B4A2B6AADB700FDE7D5 /* mapbox.places.san.francisco.json */; }; @@ -494,6 +498,8 @@ 042477C12B7290E700D870D5 /* SearchEngineGeocodingIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchEngineGeocodingIntegrationTests.swift; sourceTree = ""; }; 042477C42B72CCB000D870D5 /* geocoding-reverse-geocoding.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "geocoding-reverse-geocoding.json"; sourceTree = ""; }; 043A3D4C2B30F38300DB681B /* CoreAddress+AddressComponents.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CoreAddress+AddressComponents.swift"; sourceTree = ""; }; + 04AB0B792B6AF37800FDE7D5 /* DiscoverIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiscoverIntegrationTests.swift; sourceTree = ""; }; + 04AB0B7C2B6B043C00FDE7D5 /* category-hotel-search-along-route-jp.json */ = {isa = PBXFileReference; explicitFileType = text.json; path = "category-hotel-search-along-route-jp.json"; sourceTree = ""; }; 04970F8C2B7A97C900213763 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; 04AB0B4A2B6AADB700FDE7D5 /* mapbox.places.san.francisco.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = mapbox.places.san.francisco.json; sourceTree = ""; }; 04BBC6332B61898F00E24E99 /* LocalhostMockServiceProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalhostMockServiceProvider.swift; sourceTree = ""; }; @@ -1400,6 +1406,7 @@ 2CE1B9FA2A13D412005B043F /* address-retrieve-san-francisco.json */, 2CE1B9F92A13D412005B043F /* address-suggestions-san-francisco.json */, 2CD8AC5129F28D6900C47BE4 /* retrieve-poi.json */, + 04AB0B7C2B6B043C00FDE7D5 /* category-hotel-search-along-route-jp.json */, 2CD8AC4029F1D38800C47BE4 /* suggestions-category-with-coordinates.json */, 2CD8AC4129F1D38800C47BE4 /* suggestions-with-coordinates.json */, 2CD8AC4229F1D38800C47BE4 /* suggestions-with-mixed-coordinates.json */, @@ -1521,6 +1528,7 @@ F9ACA6162642C18200F50CD4 /* SearchEngineIntegrationTests.swift */, 042477C12B7290E700D870D5 /* SearchEngineGeocodingIntegrationTests.swift */, F99190422645ABE6009927A6 /* CategorySearchEngineIntegrationTests.swift */, + 04AB0B792B6AF37800FDE7D5 /* DiscoverIntegrationTests.swift */, F9C5572C2670C88E00BE8B94 /* Info.plist */, ); path = MapboxSearchIntegrationTests; @@ -2104,6 +2112,7 @@ 042477C62B72CCB000D870D5 /* geocoding-reverse-geocoding.json in Resources */, 2CD8AC4429F1D38800C47BE4 /* suggestions-category-with-coordinates.json in Resources */, F9B62CCB264BCC2600492999 /* suggestions-empty.json in Resources */, + 048823492B6B0A9D00C770AA /* category-hotel-search-along-route-jp.json in Resources */, 04AB0B4C2B6AADB700FDE7D5 /* mapbox.places.san.francisco.json in Resources */, F9ACA6182642C48C00F50CD4 /* recursion.json in Resources */, F9B62CC8264BC61600492999 /* category-cafe.json in Resources */, @@ -2134,6 +2143,7 @@ F907440F261B00000091899C /* suggestions-san-francisco.json in Resources */, F94FFA4826453D410019ED9B /* reverse-geocoding-sbs.json in Resources */, 2CD8AC4B29F1D38800C47BE4 /* suggestions-with-mixed-coordinates.json in Resources */, + 0488234A2B6B0A9E00C770AA /* category-hotel-search-along-route-jp.json in Resources */, 2CD8AC5429F28D6900C47BE4 /* retrieve-poi.json in Resources */, 042477C72B72CCB000D870D5 /* geocoding-reverse-geocoding.json in Resources */, F9074425261B0DF70091899C /* retrieve-san-francisco.json in Resources */, @@ -2154,6 +2164,7 @@ 042477C52B72CCB000D870D5 /* geocoding-reverse-geocoding.json in Resources */, 2CD8AC4329F1D38800C47BE4 /* suggestions-category-with-coordinates.json in Resources */, F9C557A52670CB0400BE8B94 /* suggestions-empty.json in Resources */, + 048823482B6B0A9D00C770AA /* category-hotel-search-along-route-jp.json in Resources */, 04AB0B4B2B6AADB700FDE7D5 /* mapbox.places.san.francisco.json in Resources */, F9C557A62670CB0400BE8B94 /* recursion.json in Resources */, F9C557A72670CB0400BE8B94 /* category-cafe.json in Resources */, @@ -2670,6 +2681,7 @@ F9C557C12670CD8C00BE8B94 /* CoreSearchOptions+Samples.swift in Sources */, 1420F31C29A2800300D4A511 /* CoreSearchResultStub+Samples.swift in Sources */, F9C557B72670CC5600BE8B94 /* CoreSearchResultStub.swift in Sources */, + 04AB0B7B2B6AF43E00FDE7D5 /* DiscoverIntegrationTests.swift in Sources */, F9C557BF2670CD4300BE8B94 /* CoreRequestOptions+Samples.swift in Sources */, F9C557BB2670CCC000BE8B94 /* SearchResultType+Extensions.swift in Sources */, F9C557BA2670CCAB00BE8B94 /* TestDataProviderRecord.swift in Sources */, diff --git a/Sources/MapboxSearch/PublicAPI/Common/Models/Country/Country.swift b/Sources/MapboxSearch/PublicAPI/Common/Models/Country/Country.swift index 169fe908b..f28ef6856 100644 --- a/Sources/MapboxSearch/PublicAPI/Common/Models/Country/Country.swift +++ b/Sources/MapboxSearch/PublicAPI/Common/Models/Country/Country.swift @@ -3,7 +3,7 @@ import Foundation public struct Country: Equatable { public let countryCode: String - /// Country model initializier + /// Country model initializer /// - Parameter countryCode: Permitted values are ISO 3166-1 alpha 2 country codes (e.g. US, DE, GB) public init?(countryCode: String) { guard ISO3166_1_alpha2(rawValue: countryCode.uppercased()) != nil else { @@ -12,4 +12,23 @@ public struct Country: Equatable { self.countryCode = countryCode.lowercased() } + + init(code: ISO3166_1_alpha2) { + self.countryCode = code.rawValue.lowercased() + } + + /// Detect the system region ISO3166\_1\_Alpha2 identifier and return an instance for it + static var `default`: Self? { + if #available(iOS 16, *) { + return Country(countryCode: Locale.current.region?.identifier ?? "") + } else { + let regionComponents = Locale.current.identifier.components(separatedBy: "_") + if regionComponents.count >= 2 { + let countryIdentifier = regionComponents[1] + return Country(countryCode: countryIdentifier) + } else { + return nil + } + } + } } diff --git a/Sources/MapboxSearch/PublicAPI/Use Cases/Discover API/Discover.swift b/Sources/MapboxSearch/PublicAPI/Use Cases/Discover API/Discover.swift index 591116950..c2f570cc3 100644 --- a/Sources/MapboxSearch/PublicAPI/Use Cases/Discover API/Discover.swift +++ b/Sources/MapboxSearch/PublicAPI/Use Cases/Discover API/Discover.swift @@ -59,9 +59,11 @@ extension Discover { userActivityReporter.reportActivity(forComponent: "discover-search-nearby") let searchOptions = SearchOptions( + countries: [options.country?.countryCode].compactMap { $0 }, languages: [options.language.languageCode], limit: options.limit, - proximity: proximity + proximity: proximity, + origin: options.origin ) search(for: query, with: searchOptions, completion: completion) @@ -85,10 +87,12 @@ extension Discover { userActivityReporter.reportActivity(forComponent: "discover-search-in-area") let searchOptions = SearchOptions( + countries: [options.country?.countryCode].compactMap { $0 }, languages: [options.language.languageCode], limit: options.limit, - proximity: proximity, - boundingBox: region + proximity: proximity ?? options.proximity, + boundingBox: region, + origin: options.origin ) search(for: query, with: searchOptions, completion: completion) @@ -110,8 +114,11 @@ extension Discover { userActivityReporter.reportActivity(forComponent: "discover-search-along-the-route") let searchOptions = SearchOptions( + countries: [options.country?.countryCode].compactMap { $0 }, languages: [options.language.languageCode], limit: options.limit, + proximity: options.proximity, + origin: options.origin, routeOptions: route ) diff --git a/Sources/MapboxSearch/PublicAPI/Use Cases/Discover API/Models/Discover+Options.swift b/Sources/MapboxSearch/PublicAPI/Use Cases/Discover API/Models/Discover+Options.swift index bbaf21d9f..fec0f11b1 100644 --- a/Sources/MapboxSearch/PublicAPI/Use Cases/Discover API/Models/Discover+Options.swift +++ b/Sources/MapboxSearch/PublicAPI/Use Cases/Discover API/Models/Discover+Options.swift @@ -15,12 +15,31 @@ extension Discover { /// English (en) language parameter, but Frankreich (“France”) with a German (de) language parameter. public let language: Language + /// See ``MapboxSearch.Country.ISO3166_1_alpha2`` for the list of ISO 3166 alpha 2 country codes. + /// The default value is nil. + public let country: Country? + + /// Bias the response to favor results that are closer to a specific location. + /// When both proximity and origin are provided, origin is interpreted as the target of a route, while proximity + /// indicates the current user location. + public let proximity: CLLocationCoordinate2D? + + /// The location from which to calculate distance. When both proximity and origin are provided, origin is + /// interpreted as the target of a route, while proximity indicates the current user location. + public let origin: CLLocationCoordinate2D? + public init( limit: Int = 10, - language: Language? = nil + language: Language? = nil, + country: Country? = nil, + proximity: CLLocationCoordinate2D? = nil, + origin: CLLocationCoordinate2D? = nil ) { self.limit = limit self.language = language ?? .default + self.country = country + self.proximity = proximity + self.origin = origin } } } diff --git a/Tests/MapboxSearchIntegrationTests/DiscoverIntegrationTests.swift b/Tests/MapboxSearchIntegrationTests/DiscoverIntegrationTests.swift new file mode 100644 index 000000000..620a11a1b --- /dev/null +++ b/Tests/MapboxSearchIntegrationTests/DiscoverIntegrationTests.swift @@ -0,0 +1,46 @@ +import CoreLocation +@testable import MapboxSearch +import XCTest + +class DiscoverIntegrationTests: MockServerIntegrationTestCase { + lazy var searchEngine = Discover(locationProvider: DefaultLocationProvider()) + + func testCategorySearchAlongRouteWithCountryProximityOrigin() throws { + try server.setResponse(.categoryHotelSearchAlongRoute_JP) + let expectation = XCTestExpectation(description: "Expecting results") + + let coordinate1 = CLLocationCoordinate2D(latitude: 35.655614, longitude: 139.7081684) + let coordinate2 = CLLocationCoordinate2D(latitude: 35.6881616, longitude: 139.6994339) + let coordinates = [coordinate1, coordinate2] + + let mapboxSearchRoute = MapboxSearch.Route(coordinates: coordinates) + let rOptions: MapboxSearch.RouteOptions = RouteOptions(route: mapboxSearchRoute, time: 1000) + + let discoverOptions = Discover.Options( + limit: 10, + language: nil, + country: Country(countryCode: "jp"), + proximity: CLLocationCoordinate2D( + latitude: 35.6634363, + longitude: 139.7394536 + ), + origin: CLLocationCoordinate2D(latitude: 35.66580, longitude: 139.74609) + ) + + searchEngine.search( + for: Discover.Query.Category.canonicalName("hotel"), + route: rOptions, + options: discoverOptions + ) { result in + switch result { + case .success(let searchResults): + XCTAssertFalse(searchResults.isEmpty) + expectation.fulfill() + case .failure: + XCTFail("Error not expected") + } + expectation.fulfill() + } + wait(for: [expectation], timeout: 10) + } +} diff --git a/Tests/MapboxSearchUITests/MockWebServer/MockResponse.swift b/Tests/MapboxSearchUITests/MockWebServer/MockResponse.swift index 613d561fd..61aa6ca01 100644 --- a/Tests/MapboxSearchUITests/MockWebServer/MockResponse.swift +++ b/Tests/MapboxSearchUITests/MockWebServer/MockResponse.swift @@ -1,6 +1,17 @@ import Foundation enum MockResponse { + enum Endpoint: String { + case suggest + case retrieve + case reverse + case multiRetrieve = "retrieve/multi" + case categoryCafe = "cafe" + case categoryHotel = "hotel" + case addressSuggest = "autofill/suggest" + case addressRetrieve = "autofill/retrieve" + } + case suggestEmpty case suggestMinsk case suggestSanFrancisco @@ -22,6 +33,7 @@ enum MockResponse { case reverseGeocoding case reverseGeocodingSBS case categoryCafe + case categoryHotelSearchAlongRoute_JP var filepath: String { let bundle = Bundle(for: MockWebServer.self) @@ -60,6 +72,8 @@ enum MockResponse { return bundle.path(forResource: "retrieve-multi", ofType: "json")! case .categoryCafe: return bundle.path(forResource: "category-cafe", ofType: "json")! + case .categoryHotelSearchAlongRoute_JP: + return bundle.path(forResource: "category-hotel-search-along-route-jp", ofType: "json")! case .suggestAddressSanFrancisco: return bundle.path(forResource: "address-suggestions-san-francisco", ofType: "json")! case .retrieveAddressSanFrancisco: diff --git a/Tests/MapboxSearchUITests/MockWebServer/MockWebServer.swift b/Tests/MapboxSearchUITests/MockWebServer/MockWebServer.swift index c2ea48815..ce75d9f8f 100644 --- a/Tests/MapboxSearchUITests/MockWebServer/MockWebServer.swift +++ b/Tests/MapboxSearchUITests/MockWebServer/MockWebServer.swift @@ -73,7 +73,8 @@ extension MockWebServer { .recursion, .reverseGeocoding, .reverseGeocodingSBS, - .categoryCafe: + .categoryCafe, + .categoryHotelSearchAlongRoute_JP: return .get case .multiRetrieve, @@ -127,7 +128,7 @@ extension MockWebServer { case .multiRetrieve: path += "/retrieve/multi" - case .categoryCafe: + case .categoryCafe, .categoryHotelSearchAlongRoute_JP: path += "/category/:category" } diff --git a/Tests/MapboxSearchUITests/MockWebServer/category-hotel-search-along-route-jp.json b/Tests/MapboxSearchUITests/MockWebServer/category-hotel-search-along-route-jp.json new file mode 100644 index 000000000..a570f0348 --- /dev/null +++ b/Tests/MapboxSearchUITests/MockWebServer/category-hotel-search-along-route-jp.json @@ -0,0 +1,687 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "geometry": { + "coordinates": [ + 139.73952222241294, + 35.664124999576146 + ], + "type": "Point" + }, + "properties": { + "feature_name": "ホテルヴィラフォンテーヌグランド東京六本木", + "matching_name": "ホテルヴィラフォンテーヌグランド東京六本木", + "highlighted_name": "ホテルヴィラフォンテーヌグランド東京六本木", + "description": "東京都港区六本木1-6-2", + "place_name": "ホテルヴィラフォンテーヌグランド東京六本木, 東京都港区六本木1-6-2", + "id": "dXJuOm1ieHBvaS1qcG46NTdjYzExMWUzZTQ0NDYzOTczY2NkZTgwZmI4NWYyYTI4ZTYxYmYyNjQ0Y2MzZmU0N2Q0NDU0ZmIzM2ExNjlhNw", + "place_type": [ + "poi" + ], + "context": [ + { + "layer": "address", + "localized_layer": "address", + "name": "東京都港区六本木1-6-2" + }, + { + "layer": "street", + "localized_layer": "street", + "name": "六本木1-6-2" + }, + { + "layer": "postcode", + "localized_layer": "postcode", + "name": "106-0032" + }, + { + "layer": "place", + "localized_layer": "place", + "name": "港区" + }, + { + "layer": "region", + "localized_layer": "region", + "name": "東京都" + } + ], + "maki": "lodging", + "poi_category": [ + "トラベル>ホテル", + "トラベル" + ], + "poi_category_ids": [ + "トラベル>ホテル", + "トラベル" + ], + "internal_id": "Y2aAgIL8TAA=.42eAgMSCTN2C_Ezd4tSisszkVAA=.PcG5CQAgDABA57GQxI9sIwEtRE2R0ukVBO-seXYT7VImS12sw2HwgPeHiXyGCHQA", + "external_ids": { + "zenrin_landmark": "13201010000000000158260408", + "mbx_poi": "dXJuOm1ieHBvaS1qcG46NTdjYzExMWUzZTQ0NDYzOTczY2NkZTgwZmI4NWYyYTI4ZTYxYmYyNjQ0Y2MzZmU0N2Q0NDU0ZmIzM2ExNjlhNw" + }, + "metadata": { + "iso_3166_1": "JP", + "iso_3166_2": "JP-13" + }, + "routable_points": [ + { + "name": "POI", + "coordinates": [ + 139.73991944419012, + 35.66394444465637 + ] + } + ] + } + }, + { + "type": "Feature", + "geometry": { + "coordinates": [ + 139.739588, + 35.66448 + ], + "type": "Point" + }, + "properties": { + "feature_name": "ヴィラフォンテーヌ六本木", + "matching_name": "ヴィラフォンテーヌ六本木", + "highlighted_name": "ヴィラフォンテーヌ六本木", + "description": "東京都港区六本木1-6-2", + "place_name": "ヴィラフォンテーヌ六本木, 東京都港区六本木1-6-2", + "id": "dXJuOm1ieHBvaS1qcG46OTBmNDBmOGZmZWI4Mzg2MmMzNjI3ZjJhZWFiODVhYmQ3MDg4ZTk3NmY4YzI2MjMzN2JlMGY3NzA4MDAzYzk0Nw", + "place_type": [ + "poi" + ], + "context": [ + { + "layer": "address", + "localized_layer": "address", + "name": "東京都港区六本木1-6-2" + }, + { + "layer": "street", + "localized_layer": "street", + "name": "六本木1-6-2" + }, + { + "layer": "postcode", + "localized_layer": "postcode", + "name": "106-0032" + }, + { + "layer": "place", + "localized_layer": "place", + "name": "港区" + }, + { + "layer": "region", + "localized_layer": "region", + "name": "東京都" + } + ], + "maki": "lodging", + "poi_category": [ + "トラベル>ホテル", + "トラベル" + ], + "poi_category_ids": [ + "トラベル>ホテル", + "トラベル" + ], + "internal_id": "Y2aAgIL8TAA=.42eAgMSCTN2C_Ezd4tSisszkVAA=.U2aAgLT80qLiwtLEolS95DRTCzNjU8Mk89REE2NjI8tEoIBRUhoA", + "external_ids": { + "foursquare": "cf586351b7ea43329af582bf", + "mbx_poi": "dXJuOm1ieHBvaS1qcG46OTBmNDBmOGZmZWI4Mzg2MmMzNjI3ZjJhZWFiODVhYmQ3MDg4ZTk3NmY4YzI2MjMzN2JlMGY3NzA4MDAzYzk0Nw" + }, + "metadata": { + "iso_3166_1": "JP", + "iso_3166_2": "JP-13" + }, + "routable_points": [ + { + "name": "POI", + "coordinates": [ + 139.7399993461539, + 35.66439773076928 + ] + } + ] + } + }, + { + "type": "Feature", + "geometry": { + "coordinates": [ + 139.738233, + 35.663812 + ], + "type": "Point" + }, + "properties": { + "feature_name": "朝日六本木マンション", + "matching_name": "朝日六本木マンション", + "highlighted_name": "朝日六本木マンション", + "description": "東京都港区六本木3-2-19", + "place_name": "朝日六本木マンション, 東京都港区六本木3-2-19", + "id": "dXJuOm1ieHBvaS1qcG46NTJkYTI1ZDgxMDAzMDQzMTYzMThlOTNjYjM5MjljNTI2NTExYWFiZTk1YWNiNzY5NGQ0OGI2ODgzMzBmNzQ2Yg", + "place_type": [ + "poi" + ], + "context": [ + { + "layer": "address", + "localized_layer": "address", + "name": "東京都港区六本木3-2-19" + }, + { + "layer": "street", + "localized_layer": "street", + "name": "六本木3-2-19" + }, + { + "layer": "postcode", + "localized_layer": "postcode", + "name": "106-0032" + }, + { + "layer": "place", + "localized_layer": "place", + "name": "港区" + }, + { + "layer": "region", + "localized_layer": "region", + "name": "東京都" + } + ], + "maki": "lodging", + "poi_category": [ + "トラベル>ホテル", + "トラベル" + ], + "poi_category_ids": [ + "トラベル>ホテル", + "トラベル" + ], + "internal_id": "Y2aAgIL8TAA=.42eAgMSCTN2C_Ezd4tSisszkVAA=.U2aAgLT80qLiwtLEolQ9c1Mzk7Q0y2SzFBMjE8NkC6OUJDNLk-RkAA==", + "external_ids": { + "foursquare": "7564ff9c6d4241c82db694cc", + "mbx_poi": "dXJuOm1ieHBvaS1qcG46NTJkYTI1ZDgxMDAzMDQzMTYzMThlOTNjYjM5MjljNTI2NTExYWFiZTk1YWNiNzY5NGQ0OGI2ODgzMzBmNzQ2Yg" + }, + "metadata": { + "iso_3166_1": "JP", + "iso_3166_2": "JP-13" + }, + "routable_points": [ + { + "name": "POI", + "coordinates": [ + 139.73824858754253, + 35.66371691599058 + ] + } + ] + } + }, + { + "type": "Feature", + "geometry": { + "coordinates": [ + 139.738795, + 35.664395 + ], + "type": "Point" + }, + "properties": { + "feature_name": "ホテルヴィラフォンテーヌ六本木", + "matching_name": "ホテルヴィラフォンテーヌ六本木", + "highlighted_name": "ホテルヴィラフォンテーヌ六本木", + "description": "東京都港区六本木1-6-2", + "place_name": "ホテルヴィラフォンテーヌ六本木, 東京都港区六本木1-6-2", + "id": "dXJuOm1ieHBvaS1qcG46YTRjOTFlNzQwZmI5MDZkYzRhNjM2MDZkM2M3OWEyNmExNWQ0NTg3NGQ1MTE2M2JjODc1MDUxNjNmOGNkMjgxNg", + "place_type": [ + "poi" + ], + "context": [ + { + "layer": "address", + "localized_layer": "address", + "name": "東京都港区六本木1-6-2" + }, + { + "layer": "street", + "localized_layer": "street", + "name": "六本木1-6-2" + }, + { + "layer": "postcode", + "localized_layer": "postcode", + "name": "106-0032" + }, + { + "layer": "place", + "localized_layer": "place", + "name": "港区" + }, + { + "layer": "region", + "localized_layer": "region", + "name": "東京都" + } + ], + "maki": "lodging", + "poi_category": [ + "トラベル>ホテル", + "トラベル" + ], + "poi_category_ids": [ + "トラベル>ホテル", + "トラベル" + ], + "internal_id": "Y2aAgIL8TAA=.42eAgMSCTN2C_Ezd4tSisszkVAA=.U2aAgLT80qLiwtLEolQ9k6RUUxOjNGMjE1PzRFNLY-NkE_PEJENTAA==", + "external_ids": { + "mbx_poi": "dXJuOm1ieHBvaS1qcG46YTRjOTFlNzQwZmI5MDZkYzRhNjM2MDZkM2M3OWEyNmExNWQ0NTg3NGQ1MTE2M2JjODc1MDUxNjNmOGNkMjgxNg", + "foursquare": "4be542f32457a5933c47ab15" + }, + "metadata": { + "iso_3166_1": "JP", + "iso_3166_2": "JP-13" + }, + "routable_points": [ + { + "name": "POI", + "coordinates": [ + 139.73879371353684, + 35.664395357647436 + ] + } + ] + } + }, + { + "type": "Feature", + "geometry": { + "coordinates": [ + 139.737644, + 35.664943 + ], + "type": "Point" + }, + "properties": { + "feature_name": "ヴィラフォンテーヌ六本木ANNEX", + "matching_name": "ヴィラフォンテーヌ六本木ANNEX", + "highlighted_name": "ヴィラフォンテーヌ六本木ANNEX", + "description": "東京都港区六本木3-2-7", + "place_name": "ヴィラフォンテーヌ六本木ANNEX, 東京都港区六本木3-2-7", + "id": "dXJuOm1ieHBvaS1qcG46MWNiMWMzZmQwM2IzNDY5MGIwYzc2NjY3MjY0ZTkxZWY1ZjQyNmMxMDI3ZTgwYTAzNjUyOWM4M2Y4NzQ5YTQwMg", + "place_type": [ + "poi" + ], + "context": [ + { + "layer": "address", + "localized_layer": "address", + "name": "東京都港区六本木3-2-7" + }, + { + "layer": "street", + "localized_layer": "street", + "name": "六本木3-2-7" + }, + { + "layer": "postcode", + "localized_layer": "postcode", + "name": "106-0032" + }, + { + "layer": "place", + "localized_layer": "place", + "name": "東京都" + }, + { + "layer": "region", + "localized_layer": "region", + "name": "東京都" + } + ], + "maki": "lodging", + "poi_category": [ + "トラベル>ホテル", + "トラベル" + ], + "poi_category_ids": [ + "トラベル>ホテル", + "トラベル" + ], + "internal_id": "Y2aAgIL8TAA=.42eAgMSCTN2C_Ezd4tSisszkVAA=.U2aAgLT80qLiwtLEolQ94zRLi1TzpETTRIs0k2TDVGNzM5PUtERTAA==", + "external_ids": { + "foursquare": "3f98e7ba5a8f4c1e3764efa5", + "mbx_poi": "dXJuOm1ieHBvaS1qcG46MWNiMWMzZmQwM2IzNDY5MGIwYzc2NjY3MjY0ZTkxZWY1ZjQyNmMxMDI3ZTgwYTAzNjUyOWM4M2Y4NzQ5YTQwMg" + }, + "metadata": { + "iso_3166_1": "JP", + "iso_3166_2": "JP-13" + }, + "routable_points": [ + { + "name": "POI", + "coordinates": [ + 139.7376750605189, + 35.66520018109675 + ] + } + ] + } + }, + { + "type": "Feature", + "geometry": { + "coordinates": [ + 139.737505, + 35.66491 + ], + "type": "Point" + }, + "properties": { + "feature_name": "六本木アネックス", + "matching_name": "六本木アネックス", + "highlighted_name": "六本木アネックス", + "description": "東京都港区六本木3-13-3", + "place_name": "六本木アネックス, 東京都港区六本木3-13-3", + "id": "dXJuOm1ieHBvaS1qcG46ZDZkMWE0NmQzMDZkNDFkMmZmNjJjMjY1OTRlZTllZTAxMzUyMzdjOTU3MWJhM2ZmOTUyYjYxNjVjNjRhODRhZg", + "place_type": [ + "poi" + ], + "context": [ + { + "layer": "address", + "localized_layer": "address", + "name": "東京都港区六本木3-13-3" + }, + { + "layer": "street", + "localized_layer": "street", + "name": "六本木3-13-3" + }, + { + "layer": "postcode", + "localized_layer": "postcode", + "name": "106-0032" + }, + { + "layer": "place", + "localized_layer": "place", + "name": "東京都" + }, + { + "layer": "region", + "localized_layer": "region", + "name": "東京都" + } + ], + "maki": "lodging", + "poi_category": [ + "トラベル>ホテル", + "トラベル" + ], + "poi_category_ids": [ + "トラベル>ホテル", + "トラベル" + ], + "internal_id": "Y2aAgIL8TAA=.42eAgMSCTN2C_Ezd4tSisszkVAA=.U2aAgLT80qLiwtLEolQ9kxRDU0vjZAMj0-SUREMTY-OUJCOzxBQzAA==", + "external_ids": { + "mbx_poi": "dXJuOm1ieHBvaS1qcG46ZDZkMWE0NmQzMDZkNDFkMmZmNjJjMjY1OTRlZTllZTAxMzUyMzdjOTU3MWJhM2ZmOTUyYjYxNjVjNjRhODRhZg", + "foursquare": "4d1593c025cda1433db26ad6" + }, + "metadata": { + "iso_3166_1": "JP", + "iso_3166_2": "JP-13" + }, + "routable_points": [ + { + "name": "POI", + "coordinates": [ + 139.73754198704972, + 35.66521625277177 + ] + } + ] + } + }, + { + "type": "Feature", + "geometry": { + "coordinates": [ + 139.7374694445398, + 35.6616999997033 + ], + "type": "Point" + }, + "properties": { + "feature_name": "アパホテル&リゾート六本木駅東", + "matching_name": "アパホテル&リゾート六本木駅東", + "highlighted_name": "アパホテル&リゾート六本木駅東", + "description": "東京都港区六本木3-18-6", + "place_name": "アパホテル&リゾート六本木駅東, 東京都港区六本木3-18-6", + "id": "dXJuOm1ieHBvaS1qcG46ZTg3ODMxMjI4NTZkMzIyNzQ5YjUzZGQxMTRmYzU1OGFiYWMxZGE5N2JlNTllNjIwZmU2NDM3M2EyY2YxMjRlMA", + "place_type": [ + "poi" + ], + "context": [ + { + "layer": "address", + "localized_layer": "address", + "name": "東京都港区六本木3-18-6" + }, + { + "layer": "street", + "localized_layer": "street", + "name": "六本木3-18-6" + }, + { + "layer": "postcode", + "localized_layer": "postcode", + "name": "106-0032" + }, + { + "layer": "place", + "localized_layer": "place", + "name": "東京都" + }, + { + "layer": "region", + "localized_layer": "region", + "name": "東京都" + } + ], + "maki": "lodging", + "poi_category": [ + "トラベル>ホテル", + "トラベル" + ], + "poi_category_ids": [ + "トラベル>ホテル", + "トラベル" + ], + "internal_id": "Y2aAgIL8TAA=.42eAgMSCTN2C_Ezd4tSisszkVAA=.LcAxDgAQDABA_5FItQSvkSYMgg4dvd7AWfOcLjqkLpa2WafzhOAB4SPIKVLJGFK5", + "external_ids": { + "mbx_poi": "dXJuOm1ieHBvaS1qcG46ZTg3ODMxMjI4NTZkMzIyNzQ5YjUzZGQxMTRmYzU1OGFiYWMxZGE5N2JlNTllNjIwZmU2NDM3M2EyY2YxMjRlMA", + "zenrin_landmark": "132010200000000308753982479" + }, + "metadata": { + "iso_3166_1": "JP", + "iso_3166_2": "JP-13" + }, + "routable_points": [ + { + "name": "POI", + "coordinates": [ + 139.73765833324856, + 35.66126111136542 + ] + } + ] + } + }, + { + "type": "Feature", + "geometry": { + "coordinates": [ + 139.73579722219043, + 35.66213611072964 + ], + "type": "Point" + }, + "properties": { + "feature_name": "三井ガーデンホテル六本木プレミア", + "matching_name": "三井ガーデンホテル六本木プレミア", + "highlighted_name": "三井ガーデンホテル六本木プレミア", + "description": "東京都港区六本木3-15-17", + "place_name": "三井ガーデンホテル六本木プレミア, 東京都港区六本木3-15-17", + "id": "dXJuOm1ieHBvaS1qcG46MzFkYWQ3MGQ3YWRiNWRiMDhhYjU2MmZkYzQyZmJhYzM3ZWQ3YzY5ZjQ4MWYwNTEwMTdiMWY0OWFiOGExN2QzMg", + "place_type": [ + "poi" + ], + "context": [ + { + "layer": "address", + "localized_layer": "address", + "name": "東京都港区六本木3-15-17" + }, + { + "layer": "street", + "localized_layer": "street", + "name": "六本木3-15-17" + }, + { + "layer": "postcode", + "localized_layer": "postcode", + "name": "106-0032" + }, + { + "layer": "place", + "localized_layer": "place", + "name": "東京都" + }, + { + "layer": "region", + "localized_layer": "region", + "name": "東京都" + } + ], + "maki": "lodging", + "poi_category": [ + "トラベル>ホテル", + "トラベル" + ], + "poi_category_ids": [ + "トラベル>ホテル", + "トラベル" + ], + "internal_id": "Y2aAgIL8TAA=.42eAgMSCTN2C_Ezd4tSisszkVAA=.U2aAgLT80qLiwtLEolQ901TDtFSTRCPTRGNDU2MDAwOL1OREQyMTAA==", + "external_ids": { + "zenrin_landmark": "132010100000000005763689853", + "mbx_poi": "dXJuOm1ieHBvaS1qcG46MzFkYWQ3MGQ3YWRiNWRiMDhhYjU2MmZkYzQyZmJhYzM3ZWQ3YzY5ZjQ4MWYwNTEwMTdiMWY0OWFiOGExN2QzMg", + "foursquare": "5e1fe4a25a31530008eca124" + }, + "metadata": { + "iso_3166_1": "JP", + "iso_3166_2": "JP-13" + }, + "routable_points": [ + { + "name": "POI", + "coordinates": [ + 139.73587222231757, + 35.66180555555555 + ] + } + ] + } + }, + { + "type": "Feature", + "geometry": { + "coordinates": [ + 139.737397222254, + 35.666294444402055 + ], + "type": "Point" + }, + "properties": { + "feature_name": "アパホテル六本木SIX", + "matching_name": "アパホテル六本木SIX", + "highlighted_name": "アパホテル六本木SIX", + "description": "東京都港区六本木2-3-11", + "place_name": "アパホテル六本木SIX, 東京都港区六本木2-3-11", + "id": "dXJuOm1ieHBvaS1qcG46YTJmMGRhOTk4MmE5MTRmY2ExMTdlNjE4MjQ3YzkxMDA2NDczNGUzY2M1ZjM3NDU4YmQ3ZjMzNDNhMTgzMjYwNQ", + "place_type": [ + "poi" + ], + "context": [ + { + "layer": "address", + "localized_layer": "address", + "name": "東京都港区六本木2-3-11" + }, + { + "layer": "street", + "localized_layer": "street", + "name": "" + }, + { + "layer": "postcode", + "localized_layer": "postcode", + "name": "106-0032" + }, + { + "layer": "place", + "localized_layer": "place", + "name": "東京都" + }, + { + "layer": "region", + "localized_layer": "region", + "name": "東京都" + } + ], + "maki": "lodging", + "poi_category": [ + "トラベル>ホテル", + "トラベル", + "トラベル>民宿" + ], + "poi_category_ids": [ + "トラベル>ホテル", + "トラベル", + "トラベル>民宿" + ], + "internal_id": "Y2aAgIL8TAA=.42eAgMSCTN2C_Ezd4tSisszkVAA=.U2aAgLT80qLiwtLEolQ9k9TkRNNUc8s0c0sDE0NjUyMDg5Qk42QzAA==", + "external_ids": { + "mbx_poi": "dXJuOm1ieHBvaS1qcG46YTJmMGRhOTk4MmE5MTRmY2ExMTdlNjE4MjQ3YzkxMDA2NDczNGUzY2M1ZjM3NDU4YmQ3ZjMzNDNhMTgzMjYwNQ", + "foursquare": "4eca5e79f7904135200db3c6", + "zenrin_landmark": "132010200000000308073739182" + }, + "metadata": { + "iso_3166_1": "JP", + "iso_3166_2": "JP-13" + }, + "routable_points": [ + { + "name": "POI", + "coordinates": [ + 139.73753055546018, + 35.66614166683621 + ] + } + ] + } + } + ], + "attribution": "© 2023 Mapbox and its suppliers. All rights reserved. Use of this data is subject to the Mapbox Terms of Service. (https://www.mapbox.com/about/maps/)", + "version": "272:8f01e9d5fbb40d5c3596666f5f9e76f10d82d12b", + "response_uuid": "9bd717ca-da98-45e1-a292-b2348303c670" +}