2016-07-21 32 views
0

我实际上试图在golang中使用谷歌地图API(在使用urlfetch与应用程序引擎,当我执行一个查询,我无法得到结果的结构。解析json结构从谷歌api请求与应用引擎的golang

我的代码

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 
} 

查询结果(卷曲)

{ 
    "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" 
} 

查询结果(跟我走代码)

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

你能帮我解析一下这个查询结果吗?

感谢的

+0

它将帮助您的调试注释掉除'status'字段以外的所有内容,unmarshaller将高兴地丢弃未知字段,因此它是一个更简单的测试用例。您还可以使用['ioutil.ReadAll'](https://godoc.org/io/ioutil#example-ReadAll)记录请求正文。你可能也想尝试['http.Get()'](https://golang.org/pkg/net/http/#Get) – Plato

+0

我使用谷歌appengine,它不可能使用http 。获得 – Fantasim

回答

2

小心结构的领域案例。如果我没有记错,小写字段将被编组/解组器忽略,所以你最终会在空结构中结束。尝试将字段命名为大写。

0

需要导出具有json标记的结构字段(大写字段名称)。 你也应该补充JSON标签为您的所有结构域,JSON标签必须相同,以JSON的领域,你想解析:

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]} 
+0

如果字段名称之间的唯一区别是大写,那么JSON解码器将会处理它,因此,严格来说,如果只是大写差异,则不需要JSON标记。尽管如此,为了清晰起见,不是一个坏主意。 – Kaedys

6

来解组一个JSON为结构,它需要访问成员,使它可以更新值。为了允许访问,你必须导出结构的成员(通过大写开始成员名称)。 JSON字段也应该使用json:"<field_name>"映射到结构的成员。我已经更新了你的结构。

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"` 
} 
+0

感谢它的工作! – Fantasim

+0

不错的一个,不知道你需要装饰器还是导出的结构体成员 – Plato

+1

@Plato:无论装饰器如何,你实际上都必须有输出的字段。装饰器用于处理不同的字段名称(例如,如果您的变量命名为“UserID”,而字段命名为“user_id”)。 JSON库会自动尝试匹配只有大小写不同的字段,但不会尝试下划线等其他变体,因此您需要装饰器来处理这些情况。除非字段被导出,否则它不能对你的结构做任何事情,因为它甚至看不到该字段。 – Kaedys

0

默认编码/ JSON包元帅/解组只出口领域,所以你应该改变你的结构,以这样的事情,开始用大写字母和具有JSON:“”标签。

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