简体   繁体   中英

parse json to struct from google api request in golang with App Engine

i'm actually trying to use google map api in golang (in using urlfetch with app engine and when i execute a query i can not get the result in a structure.

my code

import (

   "google.golang.org/appengine"
   "google.golang.org/appengine/log"
   "google.golang.org/appengine/urlfetch"
   "net/http"
   "strings"
   "encoding/json"
    "encoding/gob"
    "bytes"
)

func GetCoordinatesByAddress(request *http.Request) bool {

    var results Results

    ctx := appengine.NewContext(request)
    client := urlfetch.Client(ctx)

    resp, err := client.Get("https://maps.googleapis.com/maps/api/geocode/json?address=Suresnes+France"&key=" + ApiKey)
    if err != nil {
      return false
    }

    decoder := json.NewDecoder(resp.Body)
    decoder.Decode(&results)
    log.Debugf(ctx, "", results)
}

type Results struct {
   results []Result
   status string
}

type Result struct {
   address_components []Address
   formatted_address string
   geometry Geometry
   place_id string
   types []string
}

type Address struct {
   long_name string
   short_name string
   Type []string `json:"type"`
}

type Geometry struct {
   bounds Bounds
   location LatLng
   location_type string
   viewport Bounds
}

type Bounds struct {
   northeast LatLng
   southwest LatLng
}

type LatLng struct {
   lat float64
   lng float64
}

Query results (with curl)

{
   "results" : [
      {
         "address_components" : [
            {
               "long_name" : "Suresnes",
               "short_name" : "Suresnes",
               "types" : [ "locality", "political" ]
            },
            {
               "long_name" : "Hauts-de-Seine",
               "short_name" : "Hauts-de-Seine",
               "types" : [ "administrative_area_level_2", "political" ]
            },
            {
               "long_name" : "Île-de-France",
               "short_name" : "Île-de-France",
               "types" : [ "administrative_area_level_1", "political" ]
            },
            {
               "long_name" : "France",
               "short_name" : "FR",
               "types" : [ "country", "political" ]
            },
            {
               "long_name" : "92150",
               "short_name" : "92150",
               "types" : [ "postal_code" ]
            }
         ],
         "formatted_address" : "92150 Suresnes, France",
         "geometry" : {
            "bounds" : {
               "northeast" : {
                  "lat" : 48.88276,
                  "lng" : 2.2364639
               },
               "southwest" : {
                  "lat" : 48.859284,
                  "lng" : 2.199768
               }
            },
            "location" : {
               "lat" : 48.869798,
               "lng" : 2.219033
            },
            "location_type" : "APPROXIMATE",
            "viewport" : {
               "northeast" : {
                  "lat" : 48.88276,
                  "lng" : 2.2364639
               },
               "southwest" : {
                  "lat" : 48.859284,
                  "lng" : 2.199768
               }
            }
         },
         "place_id" : "ChIJ584OtMVk5kcR4DyLaMOCCwQ",
         "types" : [ "locality", "political" ]
      }
   ],
   "status" : "OK"
}

Query result (with my go code)

DEBUG: %!(EXTRA controlgoogle.Results={[] }) 

Could you help me to parse this query results in a structure ?

Thank's

To unmarshal a JSON to struct, it needs access to the members so that it can update the value. To allow access you have to export the members of the struct(By starting the member name by upper-case). The JSON fields should be mapped to struct's members as well using json:"<field_name>" . I have updated your structure.

type Results struct {
   Results []Result `json:"results"`
   Status string `json:"status"`
}

type Result struct {
   AddressComponents []Address `json:"address_components"`
   FormattedAddress string `json:"formatted_address"`
   Geometry Geometry `json:"geometry"`
   PlaceId string `json:"place_id"`
   Types []string `json:"types"`
}

type Address struct {
   LongName string `json:"long_name"`
   ShortName string `json:"short_name"`
   Types []string `json:"types"`
}

type Geometry struct {
   Bounds Bounds `json:"bounds"`
   Location LatLng `json:"location"`
   LocationType string `json:"location_type"`
   Viewport Bounds `json:"viewport"`
}

type Bounds struct {
   Northeast LatLng `json:"northeast"`
   Southwest LatLng `json:"southwest"`
}

type LatLng struct {
   Lat float64 `json:"lat"`
   Lng float64 `json:"lng"`
}

Watch out for the structs' fields case. If i remember correctly, lowercase fields will be ignored by the marshaller/unmarshaller so you're ending up in empty structs. Try naming the fields uppercase.

You can also use a third party service like Serp API that is a Google search engine results API that already provides JSON parsing.

It's easy to integrate with GoLang:

parameter := map[string]string{
    "q":            "Coffee",
    "location":     "Portland"
}

query := newGoogleSearch(parameter)
serpResponse, err := query.json()
results := serpResponse["organic_results"].([]interface{})
first_result := results[0].(map[string]interface{})
fmt.Println(ref["title"].(string))

GitHub: https://github.com/serpapi/google-search-results-golang

Struct fields that have json tags need to be exported (Uppercase field name). Also you should add json tags for all your struct fields, json tag must be identical to the json fields which you wanted to parse:

type Address struct {
    LongName  string   `json:"long_name"`
    ShortName string   `json:"short_name"`
    Type      []string `json:"types"`
}
a := `{
    "long_name" : "Suresnes",
    "short_name" : "Suresnes",
    "types" : [ "locality", "political" ]
}`

var addr Address
err := json.NewDecoder(strings.NewReader(a)).Decode(&addr)
if err != nil {
    fmt.Println(err)
}
fmt.Printf("%+v\n", addr)


output: {LongName:Suresnes ShortName:Suresnes Type:[locality political]}

By default encoding/json package marshal/unmarshal only exported fields, so you should change your structs to something like this, started with uppercase and has json:"" tag.

type Results struct {
   Results []Result `json:"results"`
   Status string `json:"status"`
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM