Repository: googlemaps/google-maps-services-go (go)

Issue:
Add support for Address Descriptors to Geocoding
Thanks for stopping by to let us know something could be better!

---
**PLEASE READ** 

If you have a support contract with Google, please create an issue in the [support console](https://cloud.google.com/support/). This will ensure a timely response. 

Discover additional support services for the Google Maps Platform, including developer communities, technical guidance, and expert support at the Google Maps Platform [support resources page](https://developers.google.com/maps/support/). 

If your bug or feature request is not related to this particular library, please visit the Google Maps Platform [issue trackers](https://developers.google.com/maps/support/#issue_tracker).

Check for answers on StackOverflow with the [google-maps](http://stackoverflow.com/questions/tagged/google-maps) tag.

---

 **Describe the solution you'd like**
Add support for Address Descriptors in the geocoding request.

 **Additional context**
https://mapsplatform.google.com/demos/address-descriptors/

Pull request:
feat!: Address descriptors
Thank you for opening a Pull Request!

---

Before submitting your PR, there are a few things you can do to make sure it goes smoothly:
- [x ] Make sure to open a GitHub issue as a bug/feature request before writing your code!  That way we can discuss the change, evaluate designs, and agree on the general idea
- [ x] Ensure the tests and linter pass
- [x ] Code coverage does not decrease (if any source code was changed)
- [ x] Appropriate docs were updated (if necessary)

Fixes #294 🦕


Patch:
diff --git a/README.md b/README.md
index 98cced0..5b24d82 100644
--- a/README.md
+++ b/README.md
@@ -90,6 +90,37 @@ func main() {
 }
 ```
 
+Sample usage of the Geocoding API with an API key to get an [Address Descriptor](https://developers.google.com/maps/documentation/geocoding/address-descriptors/requests-address-descriptors):
+
+```go
+package main
+
+import (
+	"context"
+	"log"
+
+	"github.com/kr/pretty"
+	"googlemaps.github.io/maps"
+)
+
+func main() {
+	c, err := maps.NewClient(maps.WithAPIKey("Insert-API-Key-Here"))
+	if err != nil {
+		log.Fatalf("fatal error: %s", err)
+	}
+	r := &maps.GeocodingRequest{
+		LatLng: &LatLng{Lat: 40.714224, Lng: -73.961452},
+		EnableAddressDescriptor: True
+	}
+	reverseGeocodingResponse, _, err := c.ReverseGeocode(context.Background(), r)
+	if err != nil {
+		log.Fatalf("fatal error: %s", err)
+	}
+
+	pretty.Println(reverseGeocodingResponse)
+}
+```
+
 ## Features
 
 ### Rate limiting
diff --git a/addressdescriptor.go b/addressdescriptor.go
new file mode 100644
index 0000000..6b4d966
--- /dev/null
+++ b/addressdescriptor.go
@@ -0,0 +1,148 @@
+// Copyright 2024 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package maps
+
+import (
+	"fmt"
+)
+
+/**
+* An enum representing the relationship in space between the landmark and the target.
+*/
+type SpatialRelationship string
+
+const (
+	 // This is the default relationship when nothing more specific below
+    // applies.
+    SPATIAL_RELATIONSHIP_NEAR                   SpatialRelationship = "NEAR"
+	// The landmark has a spatial geometry and the target is within its
+	// bounds.
+    SPATIAL_RELATIONSHIP_WITHIN                 SpatialRelationship = "WITHIN"
+	// The target is directly adjacent to the landmark or landmark's access
+	// point.
+    SPATIAL_RELATIONSHIP_BESIDE                 SpatialRelationship = "BESIDE"
+	// The target is directly opposite the landmark on the other side of the
+	// road.
+    SPATIAL_RELATIONSHIP_ACROSS_THE_ROAD        SpatialRelationship = "ACROSS_THE_ROAD"
+	// On the same route as the landmark but not besides or across.
+    SPATIAL_RELATIONSHIP_DOWN_THE_ROAD          SpatialRelationship = "DOWN_THE_ROAD"
+	// Not on the same route as the landmark but a single 'turn' away.
+    SPATIAL_RELATIONSHIP_AROUND_THE_CORNER      SpatialRelationship = "AROUND_THE_CORNER"
+	// Close to the landmark's structure but further away from its access
+	// point.
+    SPATIAL_RELATIONSHIP_BEHIND                 SpatialRelationship = "BEHIND"
+)
+
+// String method for formatted output
+func (sr SpatialRelationship) String() string {
+    return string(sr)
+}
+
+/**
+* An enum representing the relationship in space between the area and the target.
+*/
+type Containment string
+
+const (
+	/**
+	* Indicates an unknown containment returned by the server.
+	*/
+    CONTAINMENT_UNSPECIFIED Containment = "CONTAINMENT_UNSPECIFIED"
+	/** The target location is within the area region, close to the center. */
+    CONTAINMENT_WITHIN                  Containment = "WITHIN"
+	/** The target location is within the area region, close to the edge. */
+    CONTAINMENT_OUTSKIRTS               Containment = "OUTSKIRTS"
+	/** The target location is outside the area region, but close by. */
+    CONTAINMENT_NEAR                    Containment = "NEAR"
+)
+
+// String method for formatted output
+func (c Containment) String() string {
+    return string(c)
+}
+
+/**
+* Localized variant of a text in a particular language.
+*/
+type LocalizedText struct {
+	// Localized string in the language corresponding to language_code below.
+    Text         string `json:"text"`
+	// The text's BCP-47 language code, such as "en-US" or "sr-Latn".
+    //
+    // For more information, see
+    // http://www.unicode.org/reports/tr35/#Unicode_locale_identifier.
+    LanguageCode string `json:"language_code"`
+}
+
+// String method for formatted output
+func (lt LocalizedText) String() string {
+    return fmt.Sprintf("(text=%s, languageCode=%s)", lt.Text, lt.LanguageCode)
+}
+
+// Landmarks that are useful at describing a location.
+type Landmark struct {
+	// The Place ID of the underlying establishment serving as the landmark.
+    // Can be used to resolve more information about the landmark through Place
+    // Details or Place Id Lookup.
+    PlaceID                     string                   `json:"place_id"`
+	// The best name for the landmark.
+    DisplayName                 LocalizedText            `json:"display_name"`
+	// One or more values indicating the type of the returned result. Please see <a
+    // href="https://developers.google.com/maps/documentation/places/web-service/supported_types">Types
+    // </a> for more detail.
+    Types                       []string                 `json:"types"`
+	// Defines the spatial relationship between the target location and the
+    // landmark.
+    SpatialRelationship         SpatialRelationship  `json:"spatial_relationship"`
+	// The straight line distance between the target location and one of the
+    // landmark's access points.
+    StraightLineDistanceMeters  float32           `json:"straight_line_distance_meters"`
+	// The travel distance along the road network between the target
+    // location's closest point on a road, and the landmark's closest access
+    // point on a road. This can be unpopulated if the landmark is disconnected
+    // from the part of the road network the target is closest to OR if the
+    // target location was not actually considered to be on the road network.
+    TravelDistanceMeters        float32               `json:"travel_distance_meters"`
+}
+
+// Precise regions that are useful at describing a location.
+type Area struct {
+	// The Place ID of the underlying area feature. Can be used to
+    // resolve more information about the area through Place Details or
+    // Place Id Lookup.
+    PlaceID     string              `json:"place_id"`
+	// The best name for the area.
+    DisplayName LocalizedText       `json:"display_name"`
+	/**
+	* An enum representing the relationship in space between the area and the target.
+	*/
+    Containment Containment     `json:"containment"`
+}
+
+/**
+ * Represents a descriptor of an address.
+ *
+ * <p>Please see <a
+ * href="https://mapsplatform.google.com/demos/address-descriptors/">Address 
+ * Descriptors</a> for more detail.
+ */
+type AddressDescriptor struct {
+	// A ranked list of nearby landmarks. The most useful (recognizable and
+  	// nearby) landmarks are ranked first.
+	Landmarks    []Landmark   `json:"landmarks"`
+	// A ranked list of containing or adjacent areas. The most useful
+  // (recognizable and precise) areas are ranked first.
+	Areas        []Area       `json:"areas"`
+}
\ No newline at end of file
diff --git a/examples/geocoding/cmdline/main.go b/examples/geocoding/cmdline/main.go
index ce71cef..c4753e7 100644
--- a/examples/geocoding/cmdline/main.go
+++ b/examples/geocoding/cmdline/main.go
@@ -41,6 +41,7 @@ var (
 	latlng       = flag.String("latlng", "", "The textual latitude/longitude value for which you wish to obtain the closest, human-readable address.")
 	resultType   = flag.String("result_type", "", "One or more address types, separated by a pipe (|).")
 	locationType = flag.String("location_type", "", "One or more location types, separated by a pipe (|).")
+	enableAddressDescriptor = flag.String("enable_address_descriptor", "", "True or False.  Whether to return the Address Descriptors in the response.")
 )
 
 func usageAndExit(msg string) {
@@ -81,6 +82,7 @@ func main() {
 	parseLatLng(*latlng, r)
 	parseResultType(*resultType, r)
 	parseLocationType(*locationType, r)
+	parseEnableAddressDescriptor(*enableAddressDescriptor, r)
 
 	resp, err := client.Geocode(context.Background(), r)
 	check(err)
@@ -187,3 +189,11 @@ func parseLocationType(locationType string, r *maps.GeocodingRequest) {
 
 	}
 }
+
+func parseEnableAddressDescriptor(enableAddressDescriptor string, r *maps.GeocodingRequest) {
+	if enableAddressDescriptor == "True" {
+		r.EnableAddressDescriptor = true
+	} else {
+		r.EnableAddressDescriptor = false
+	}
+}
diff --git a/geocoding.go b/geocoding.go
index c7785a9..cdf0dd1 100644
--- a/geocoding.go
+++ b/geocoding.go
@@ -32,9 +32,9 @@ var geocodingAPI = &apiConfig{
 }
 
 // Geocode makes a Geocoding API request
-func (c *Client) Geocode(ctx context.Context, r *GeocodingRequest) ([]GeocodingResult, error) {
+func (c *Client) Geocode(ctx context.Context, r *GeocodingRequest) (GeocodingResponse, error) {
 	if r.Address == "" && len(r.Components) == 0 && r.LatLng == nil {
-		return nil, errors.New("maps: address, components and LatLng are all missing")
+		return GeocodingResponse{}, errors.New("maps: address, components and LatLng are all missing")
 	}
 
 	var response struct {
@@ -43,38 +43,38 @@ func (c *Client) Geocode(ctx context.Context, r *GeocodingRequest) ([]GeocodingR
 	}
 
 	if err := c.getJSON(ctx, geocodingAPI, r, &response); err != nil {
-		return nil, err
+		return GeocodingResponse{}, err
 	}
 
 	if err := response.StatusError(); err != nil {
-		return nil, err
+		return GeocodingResponse{}, err
 	}
 
-	return response.Results, nil
+	return GeocodingResponse{response.Results, AddressDescriptor{}}, nil
 }
 
 // ReverseGeocode makes a Reverse Geocoding API request
-func (c *Client) ReverseGeocode(ctx context.Context, r *GeocodingRequest) ([]GeocodingResult, error) {
+func (c *Client) ReverseGeocode(ctx context.Context, r *GeocodingRequest) (GeocodingResponse, error) {
 	// Since Geocode() does not allow a nil LatLng, whereas it is allowed here
 	if r.LatLng == nil && r.PlaceID == "" {
-		return nil, errors.New("maps: LatLng and PlaceID are both missing")
+		return GeocodingResponse{}, errors.New("maps: LatLng and PlaceID are both missing")
 	}
 
 	var response struct {
 		Results []GeocodingResult `json:"results"`
+		AddressDescriptor AddressDescriptor `json:"address_descriptor"`
 		commonResponse
 	}
 
 	if err := c.getJSON(ctx, geocodingAPI, r, &response); err != nil {
-		return nil, err
+		return GeocodingResponse{}, err
 	}
 
 	if err := response.StatusError(); err != nil {
-		return nil, err
+		return GeocodingResponse{}, err
 	}
 
-	return response.Results, nil
-
+	return GeocodingResponse{response.Results, response.AddressDescriptor}, nil
 }
 
 func (r *GeocodingRequest) params() url.Values {
@@ -119,6 +119,9 @@ func (r *GeocodingRequest) params() url.Values {
 	if r.Language != "" {
 		q.Set("language", r.Language)
 	}
+	if r.EnableAddressDescriptor == true {
+		q.Set("enable_address_descriptor", "true")
+	}
 
 	return q
 }
@@ -176,12 +179,23 @@ type GeocodingRequest struct {
 	// Language is the language in which to return results. Optional.
 	Language string
 
+	// Language is the language in which to return results. Optional.
+	EnableAddressDescriptor bool
+
 	// Custom allows passing through custom parameters to the Geocoding back end.
 	// Use with caution. For more detail on why this is required, please see
 	// https://googlegeodevelopers.blogspot.com/2016/11/address-geocoding-in-google-maps-apis.html
 	Custom url.Values
 }
 
+// GeocodingResponse is the response to a Geocoding API request.
+type GeocodingResponse struct {
+	// Results is the Geocoding results
+	Results []GeocodingResult
+	// The Address Descriptor for the target in the reverse geocoding requeest
+	AddressDescriptor AddressDescriptor
+}
+
 // GeocodingResult is a single geocoded address
 type GeocodingResult struct {
 	AddressComponents []AddressComponent `json:"address_components"`


Test patch:
diff --git a/geocoding_test.go b/geocoding_test.go
index a00e285..56d76f3 100644
--- a/geocoding_test.go
+++ b/geocoding_test.go
@@ -127,72 +127,76 @@ func TestGeocodingGoogleHQ(t *testing.T) {
 
 	resp, err := c.Geocode(context.Background(), r)
 
-	if len(resp) != 1 {
-		t.Errorf("Expected length of response is 1, was %+v", len(resp))
+	if len(resp.Results) != 1 {
+		t.Errorf("Expected length of response is 1, was %+v", len(resp.Results))
 	}
 	if err != nil {
 		t.Errorf("r.Get returned non nil error: %v", err)
 	}
 
-	correctResponse := GeocodingResult{
-		AddressComponents: []AddressComponent{
+	correctResponse := GeocodingResponse{
+		Results: []GeocodingResult{
 			{
-				LongName:  "1600",
-				ShortName: "1600",
-				Types:     []string{"street_number"},
+				AddressComponents: []AddressComponent{
+					{
+						LongName:  "1600",
+						ShortName: "1600",
+						Types:     []string{"street_number"},
+					},
+					{
+						LongName:  "Amphitheatre Pkwy",
+						ShortName: "Amphitheatre Pkwy",
+						Types:     []string{"route"},
+					},
+					{
+						LongName:  "Mountain View",
+						ShortName: "Mountain View",
+						Types:     []string{"locality", "political"},
+					},
+					{
+						LongName:  "Santa Clara County",
+						ShortName: "Santa Clara County",
+						Types:     []string{"administrative_area_level_2", "political"},
+					},
+					{
+						LongName:  "California",
+						ShortName: "CA",
+						Types:     []string{"administrative_area_level_1", "political"},
+					},
+					{
+						LongName:  "United States",
+						ShortName: "US",
+						Types:     []string{"country", "political"},
+					},
+					{
+						LongName:  "94043",
+						ShortName: "94043",
+						Types:     []string{"postal_code"},
+					},
+				},
+				FormattedAddress: "1600 Amphitheatre Parkway, Mountain View, CA 94043, USA",
+				Geometry: AddressGeometry{
+					Location: LatLng{Lat: 37.4224764, Lng: -122.0842499},
+					Bounds: LatLngBounds{
+						NorthEast: LatLng{Lat: 37.4238253802915, Lng: -122.0829009197085},
+						SouthWest: LatLng{Lat: 37.4211274197085, Lng: -122.0855988802915},
+					},
+					LocationType: "ROOFTOP",
+					Viewport: LatLngBounds{
+						NorthEast: LatLng{Lat: 37.4238253802915, Lng: -122.0829009197085},
+						SouthWest: LatLng{Lat: 37.4211274197085, Lng: -122.0855988802915},
+					},
+					Types: nil,
+				},
+				PartialMatch: false,
+				PlaceID:      "ChIJ2eUgeAK6j4ARbn5u_wAGqWA",
+				Types:        []string{"street_address"},
 			},
-			{
-				LongName:  "Amphitheatre Pkwy",
-				ShortName: "Amphitheatre Pkwy",
-				Types:     []string{"route"},
-			},
-			{
-				LongName:  "Mountain View",
-				ShortName: "Mountain View",
-				Types:     []string{"locality", "political"},
-			},
-			{
-				LongName:  "Santa Clara County",
-				ShortName: "Santa Clara County",
-				Types:     []string{"administrative_area_level_2", "political"},
-			},
-			{
-				LongName:  "California",
-				ShortName: "CA",
-				Types:     []string{"administrative_area_level_1", "political"},
-			},
-			{
-				LongName:  "United States",
-				ShortName: "US",
-				Types:     []string{"country", "political"},
-			},
-			{
-				LongName:  "94043",
-				ShortName: "94043",
-				Types:     []string{"postal_code"},
-			},
-		},
-		FormattedAddress: "1600 Amphitheatre Parkway, Mountain View, CA 94043, USA",
-		Geometry: AddressGeometry{
-			Location: LatLng{Lat: 37.4224764, Lng: -122.0842499},
-			Bounds: LatLngBounds{
-				NorthEast: LatLng{Lat: 37.4238253802915, Lng: -122.0829009197085},
-				SouthWest: LatLng{Lat: 37.4211274197085, Lng: -122.0855988802915},
-			},
-			LocationType: "ROOFTOP",
-			Viewport: LatLngBounds{
-				NorthEast: LatLng{Lat: 37.4238253802915, Lng: -122.0829009197085},
-				SouthWest: LatLng{Lat: 37.4211274197085, Lng: -122.0855988802915},
-			},
-			Types: nil,
 		},
-		PartialMatch: false,
-		PlaceID:      "ChIJ2eUgeAK6j4ARbn5u_wAGqWA",
-		Types:        []string{"street_address"},
 	}
 
-	if !reflect.DeepEqual(resp[0], correctResponse) {
-		t.Errorf("expected %+v, was %+v", correctResponse, resp[0])
+	if !reflect.DeepEqual(resp, correctResponse) {
+		t.Errorf("expected %+v, was %+v", correctResponse, resp)
 	}
 }
 
@@ -310,76 +314,80 @@ func TestGeocodingReverseGeocoding(t *testing.T) {
 
 	resp, err := c.ReverseGeocode(context.Background(), r)
 
-	if len(resp) != 1 {
-		t.Errorf("expected %+v, was %+v", 1, len(resp))
+	if len(resp.Results) != 1 {
+		t.Errorf("expected %+v, was %+v", 1, len(resp.Results))
 	}
 	if err != nil {
 		t.Errorf("r.Get returned non nil error: %v", err)
 	}
 
-	correctResponse := GeocodingResult{
-		AddressComponents: []AddressComponent{
-			{
-				LongName:  "277",
-				ShortName: "277",
-				Types:     []string{"street_number"},
-			},
+	correctResponse := GeocodingResponse{
+		Results: []GeocodingResult{
 			{
-				LongName:  "Bedford Avenue",
-				ShortName: "Bedford Ave",
-				Types:     []string{"route"},
-			},
-			{
-				LongName:  "Williamsburg",
-				ShortName: "Williamsburg",
-				Types:     []string{"neighborhood", "political"},
-			},
-			{
-				LongName:  "Brooklyn",
-				ShortName: "Brooklyn",
-				Types:     []string{"sublocality", "political"},
-			},
-			{
-				LongName:  "Kings",
-				ShortName: "Kings",
-				Types:     []string{"administrative_area_level_2", "political"},
-			},
-			{
-				LongName:  "New York",
-				ShortName: "NY",
-				Types:     []string{"administrative_area_level_1", "political"},
-			},
-			{
-				LongName:  "United States",
-				ShortName: "US",
-				Types:     []string{"country", "political"},
-			},
-			{
-				LongName:  "11211",
-				ShortName: "11211",
-				Types:     []string{"postal_code"},
+				AddressComponents: []AddressComponent{
+					{
+						LongName:  "277",
+						ShortName: "277",
+						Types:     []string{"street_number"},
+					},
+					{
+						LongName:  "Bedford Avenue",
+						ShortName: "Bedford Ave",
+						Types:     []string{"route"},
+					},
+					{
+						LongName:  "Williamsburg",
+						ShortName: "Williamsburg",
+						Types:     []string{"neighborhood", "political"},
+					},
+					{
+						LongName:  "Brooklyn",
+						ShortName: "Brooklyn",
+						Types:     []string{"sublocality", "political"},
+					},
+					{
+						LongName:  "Kings",
+						ShortName: "Kings",
+						Types:     []string{"administrative_area_level_2", "political"},
+					},
+					{
+						LongName:  "New York",
+						ShortName: "NY",
+						Types:     []string{"administrative_area_level_1", "political"},
+					},
+					{
+						LongName:  "United States",
+						ShortName: "US",
+						Types:     []string{"country", "political"},
+					},
+					{
+						LongName:  "11211",
+						ShortName: "11211",
+						Types:     []string{"postal_code"},
+					},
+				},
+				FormattedAddress: "277 Bedford Avenue, Brooklyn, NY 11211, USA",
+				Geometry: AddressGeometry{
+					Location: LatLng{Lat: 40.714232, Lng: -73.9612889},
+					Bounds: LatLngBounds{
+						NorthEast: LatLng{Lat: 40.7155809802915, Lng: -73.9599399197085},
+						SouthWest: LatLng{Lat: 40.7128830197085, Lng: -73.96263788029151},
+					},
+					LocationType: "ROOFTOP",
+					Viewport: LatLngBounds{
+						NorthEast: LatLng{Lat: 40.7155809802915, Lng: -73.9599399197085},
+						SouthWest: LatLng{Lat: 40.7128830197085, Lng: -73.96263788029151},
+					},
+					Types: nil,
+				},
+				PlaceID: "ChIJd8BlQ2BZwokRAFUEcm_qrcA",
+				Types:   []string{"street_address"},
 			},
 		},
-		FormattedAddress: "277 Bedford Avenue, Brooklyn, NY 11211, USA",
-		Geometry: AddressGeometry{
-			Location: LatLng{Lat: 40.714232, Lng: -73.9612889},
-			Bounds: LatLngBounds{
-				NorthEast: LatLng{Lat: 40.7155809802915, Lng: -73.9599399197085},
-				SouthWest: LatLng{Lat: 40.7128830197085, Lng: -73.96263788029151},
-			},
-			LocationType: "ROOFTOP",
-			Viewport: LatLngBounds{
-				NorthEast: LatLng{Lat: 40.7155809802915, Lng: -73.9599399197085},
-				SouthWest: LatLng{Lat: 40.7128830197085, Lng: -73.96263788029151},
-			},
-			Types: nil,
-		},
-		PlaceID: "ChIJd8BlQ2BZwokRAFUEcm_qrcA",
-		Types:   []string{"street_address"},
 	}
 
-	if !reflect.DeepEqual(resp[0], correctResponse) {
-		t.Errorf("expected %+v, was %+v", correctResponse, resp[0])
+	if !reflect.DeepEqual(resp, correctResponse) {
+		t.Errorf("expected %+v, was %+v", correctResponse, resp)
 	}
 }
 
@@ -528,6 +536,99 @@ func TestReverseGeocodingPlaceID(t *testing.T) {
             ]
         }
     ],
+	"address_descriptor": {
+		"landmarks": [
+			{
+			"place_id": "ChIJvUbrwCCoAWARX2QiHCsn5A4",
+			"display_name": {
+				"text": "Kinkaku-ji",
+				"language_code": "en"
+			},
+			"types": [
+				"establishment",
+				"place_of_worship",
+				"point_of_interest",
+				"tourist_attraction"
+			],
+			"spatial_relationship": "NEAR",
+			"straight_line_distance_meters": 0.009104185
+			},
+			{
+			"place_id": "ChIJf2s61SCoAWARVtK8cnSu6zw",
+			"display_name": {
+				"text": "Shariden Kinkaku",
+				"language_code": "en"
+			},
+			"types": [
+				"establishment",
+				"place_of_worship",
+				"point_of_interest",
+				"tourist_attraction"
+			],
+			"spatial_relationship": "WITHIN",
+			"straight_line_distance_meters": 73.58092
+			},
+			{
+			"place_id": "ChIJXZeF2jipAWARNbF8pJDRjFc",
+			"display_name": {
+				"text": "Kyōko-chi Pond",
+				"language_code": "en"
+			},
+			"types": [
+				"establishment",
+				"park",
+				"point_of_interest"
+			],
+			"spatial_relationship": "BEHIND",
+			"straight_line_distance_meters": 57.99922
+			},
+			{
+			"place_id": "ChIJj69vLCapAWAR0FBBPEfPeAQ",
+			"display_name": {
+				"text": "鹿苑寺（金閣寺）",
+				"language_code": "ja"
+			},
+			"types": [
+				"establishment",
+				"place_of_worship",
+				"point_of_interest"
+			],
+			"spatial_relationship": "WITHIN",
+			"straight_line_distance_meters": 32.30453
+			},
+			{
+			"place_id": "ChIJ482HblCpAWARoLBXDZpv7aI",
+			"display_name": {
+				"text": "Kinkaku-ji Fence",
+				"language_code": "en"
+			},
+			"types": [
+				"establishment",
+				"point_of_interest"
+			],
+			"spatial_relationship": "WITHIN",
+			"straight_line_distance_meters": 99.38629
+			}
+		],
+		"areas": [
+			{
+			"place_id": "ChIJe9XMwiCoAWARVrQpOsYqdBE",
+			"display_name": {
+				"text": "Kinkakujicho",
+				"language_code": "en"
+			},
+			"containment" : "WITHIN"
+			},
+			{
+			"place_id": "ChIJk-6T5COoAWARa-KMWGWzrwQ",
+			"display_name": {
+				"text": "Kinkaku-ji",
+				"language_code": "en"
+			},
+			"containment" : "OUTSKIRTS"
+			}
+		]
+	},
     "status": "OK"
 }`
 
@@ -539,67 +640,122 @@ func TestReverseGeocodingPlaceID(t *testing.T) {
 	}
 
 	resp, err := c.ReverseGeocode(context.Background(), r)
-	if len(resp) != 1 {
-		t.Errorf("Expected length of response is 1, was %+v", len(resp))
+	if len(resp.Results) != 1 {
+		t.Errorf("Expected length of response is 1, was %+v", len(resp.Results))
 	}
 	if err != nil {
 		t.Errorf("r.Get returned non nil error: %v", err)
 	}
 
-	correctResponse := GeocodingResult{
-		AddressComponents: []AddressComponent{
-			{
-				LongName:  "1600",
-				ShortName: "1600",
-				Types:     []string{"street_number"},
-			},
-			{
-				LongName:  "Amphitheatre Pkwy",
-				ShortName: "Amphitheatre Pkwy",
-				Types:     []string{"route"},
-			},
-			{
-				LongName:  "Mountain View",
-				ShortName: "Mountain View",
-				Types:     []string{"locality", "political"},
-			},
+	correctResponse := GeocodingResponse{
+		Results: []GeocodingResult{
 			{
-				LongName:  "Santa Clara County",
-				ShortName: "Santa Clara County",
-				Types:     []string{"administrative_area_level_2", "political"},
-			},
-			{
-				LongName:  "California",
-				ShortName: "CA",
-				Types:     []string{"administrative_area_level_1", "political"},
-			},
-			{
-				LongName:  "United States",
-				ShortName: "US",
-				Types:     []string{"country", "political"},
-			},
-			{
-				LongName:  "94043",
-				ShortName: "94043",
-				Types:     []string{"postal_code"},
+				AddressComponents: []AddressComponent{
+					{
+						LongName:  "1600",
+						ShortName: "1600",
+						Types:     []string{"street_number"},
+					},
+					{
+						LongName:  "Amphitheatre Pkwy",
+						ShortName: "Amphitheatre Pkwy",
+						Types:     []string{"route"},
+					},
+					{
+						LongName:  "Mountain View",
+						ShortName: "Mountain View",
+						Types:     []string{"locality", "political"},
+					},
+					{
+						LongName:  "Santa Clara County",
+						ShortName: "Santa Clara County",
+						Types:     []string{"administrative_area_level_2", "political"},
+					},
+					{
+						LongName:  "California",
+						ShortName: "CA",
+						Types:     []string{"administrative_area_level_1", "political"},
+					},
+					{
+						LongName:  "United States",
+						ShortName: "US",
+						Types:     []string{"country", "political"},
+					},
+					{
+						LongName:  "94043",
+						ShortName: "94043",
+						Types:     []string{"postal_code"},
+					},
+				},
+				FormattedAddress: "1600 Amphitheatre Parkway, Mountain View, CA 94043, USA",
+				Geometry: AddressGeometry{
+					Location:     LatLng{Lat: 37.4224764, Lng: -122.0842499},
+					LocationType: "ROOFTOP",
+					Viewport: LatLngBounds{
+						NorthEast: LatLng{Lat: 37.4238253802915, Lng: -122.0829009197085},
+						SouthWest: LatLng{Lat: 37.4211274197085, Lng: -122.0855988802915},
+					},
+					Types: nil,
+				},
+				PlaceID: "ChIJ2eUgeAK6j4ARbn5u_wAGqWA",
+				Types:   []string{"street_address"},
 			},
 		},
-		FormattedAddress: "1600 Amphitheatre Parkway, Mountain View, CA 94043, USA",
-		Geometry: AddressGeometry{
-			Location:     LatLng{Lat: 37.4224764, Lng: -122.0842499},
-			LocationType: "ROOFTOP",
-			Viewport: LatLngBounds{
-				NorthEast: LatLng{Lat: 37.4238253802915, Lng: -122.0829009197085},
-				SouthWest: LatLng{Lat: 37.4211274197085, Lng: -122.0855988802915},
+		AddressDescriptor: AddressDescriptor{
+			Landmarks: []Landmark{
+				{
+					PlaceID:                     "ChIJvUbrwCCoAWARX2QiHCsn5A4",
+					DisplayName:                 LocalizedText{Text: "Kinkaku-ji", LanguageCode: "en"},
+					Types:                       []string{"establishment", "place_of_worship", "point_of_interest", "tourist_attraction"},
+					SpatialRelationship:         SPATIAL_RELATIONSHIP_NEAR,
+					StraightLineDistanceMeters:  0.009104185,
+				},
+				{
+					PlaceID:                     "ChIJf2s61SCoAWARVtK8cnSu6zw",
+					DisplayName:                 LocalizedText{Text: "Shariden Kinkaku", LanguageCode: "en"},
+					Types:                       []string{"establishment", "place_of_worship", "point_of_interest", "tourist_attraction"},
+					SpatialRelationship:         SPATIAL_RELATIONSHIP_WITHIN,
+					StraightLineDistanceMeters:  73.58092,
+				},
+				{
+					PlaceID:                     "ChIJXZeF2jipAWARNbF8pJDRjFc",
+					DisplayName:                 LocalizedText{Text: "Kyōko-chi Pond", LanguageCode: "en"},
+					Types:                       []string{"establishment", "park", "point_of_interest"},
+					SpatialRelationship:         SPATIAL_RELATIONSHIP_BEHIND,
+					StraightLineDistanceMeters:  57.99922,
+				},
+				{
+					PlaceID:                     "ChIJj69vLCapAWAR0FBBPEfPeAQ",
+					DisplayName:                 LocalizedText{Text: "鹿苑寺（金閣寺）", LanguageCode: "ja"},
+					Types:                       []string{"establishment", "place_of_worship", "point_of_interest"},
+					SpatialRelationship:         SPATIAL_RELATIONSHIP_WITHIN,
+					StraightLineDistanceMeters:  32.30453,
+				},
+				{
+					PlaceID:                     "ChIJ482HblCpAWARoLBXDZpv7aI",
+					DisplayName:                 LocalizedText{Text: "Kinkaku-ji Fence", LanguageCode: "en"},
+					Types:                       []string{"establishment", "point_of_interest"},
+					SpatialRelationship:         SPATIAL_RELATIONSHIP_WITHIN,
+					StraightLineDistanceMeters:  99.38629,
+				},
+			},
+			Areas: []Area{
+				{
+					PlaceID:                     "ChIJe9XMwiCoAWARVrQpOsYqdBE",
+					DisplayName:                 LocalizedText{Text: "Kinkakujicho", LanguageCode: "en"},
+					Containment:                 CONTAINMENT_WITHIN,
+				},
+				{
+					PlaceID:                     "ChIJk-6T5COoAWARa-KMWGWzrwQ",
+					DisplayName:                 LocalizedText{Text: "Kinkaku-ji", LanguageCode: "en"},
+					Containment:                 CONTAINMENT_OUTSKIRTS,
+				},
 			},
-			Types: nil,
 		},
-		PlaceID: "ChIJ2eUgeAK6j4ARbn5u_wAGqWA",
-		Types:   []string{"street_address"},
 	}
 
-	if !reflect.DeepEqual(resp[0], correctResponse) {
-		t.Errorf("expected %+v, was %+v", correctResponse, resp[0])
+	if !reflect.DeepEqual(resp, correctResponse) {
+		t.Errorf("expected %+v, was %+v", correctResponse, resp)
 	}
 }
 
@@ -641,11 +797,11 @@ func TestGeocodingZeroResults(t *testing.T) {
 		t.Errorf("Unexpected error for ZERO_RESULTS status")
 	}
 
-	if response == nil {
+	if response.Results == nil {
 		t.Errorf("Unexpected nil response for ZERO_RESULTS status")
 	}
 
-	if len(response) != 0 {
+	if len(response.Results) != 0 {
 		t.Errorf("Unexpected response for ZERO_RESULTS status")
 	}
 }
@@ -664,11 +820,11 @@ func TestReverseGeocodingZeroResults(t *testing.T) {
 		t.Errorf("Unexpected error for ZERO_RESULTS status")
 	}
 
-	if response == nil {
+	if response.Results == nil {
 		t.Errorf("Unexpected nil response for ZERO_RESULTS status")
 	}
 
-	if len(response) != 0 {
+	if len(response.Results) != 0 {
 		t.Errorf("Unexpected response for ZERO_RESULTS status")
 	}
 }