尝试查询API,但api响应为空

时间:2016-06-21 06:53:58

标签: api http go get

我正在尝试使用http://ip-api.com/ api通过我的IP地址获取经度和纬度。当我从浏览器或curl访问http://ip-api.com/json时,它会在json中返回正确的信息。但是当我尝试使用我的程序中的API时,API响应有一个空主体(或者似乎是这样)。

我正在尝试在此应用中执行此操作。 Ip_response_success结构是根据这里的api文档http://ip-api.com/docs/api:json

制作的
type Ip_response_success struct {
    as          string
    city        string
    country     string
    countryCode string
    isp         string
    lat         string
    lon         string
    org         string
    query       string
    region      string
    regionName  string
    status      string  
    timezone    string
    zip         string
}

func Query(url string) (Ip_response_success, error) {
    resp, err := http.Get(url)
    if err != nil {
        return Ip_response_success{}, err
    }
    fmt.Printf("%#v\n", resp)

    var ip_response Ip_response_success
    defer resp.Body.Close()
    err = json.NewDecoder(resp.Body).Decode(&ip_response)
    if err != nil {
        return Ip_response_success{}, err
    }
    body, err := ioutil.ReadAll(resp.Body)
    fmt.Printf("%#v\n", string(body))
    return ip_response, nil
}

func main() {
    ip, err := Query("http://ip-api.com/json")
    if err != nil {
        fmt.Printf("%#v\n", err)
    }
}

但最奇怪的是,反应的主体是空白的。它在响应中提供了200个状态代码,因此我假设API调用没有错误。 API没有提到任何身份验证要求或用户代理要求,当我卷曲或通过浏览器访问它时,它似乎并不需要任何特殊内容。我的程序中是否有任何错误或者我使用API​​错误了?

我尝试在代码中打印响应,但resp.body只是空白。打印http.Response结构的示例响应:

&http.Response{Status:"200 OK", StatusCode:200, Proto:"HTTP/1.1", ProtoMajor:1, 
ProtoMinor:1, Header:http.Header{"Access-Control-Allow-Origin":[]string{"*"}, 
"Content-Type":[]string{"application/json; charset=utf-8"}, "Date":
[]string{"Tue, 21 Jun 2016 06:46:57 GMT"}, "Content-Length":[]string{"340"}}, 
Body:(*http.bodyEOFSignal)(0xc820010640), ContentLength:340, TransferEncoding:
[]string(nil), Close:false, Trailer:http.Header(nil), Request:(*http.Request)
(0xc8200c6000), TLS:(*tls.ConnectionState)(nil)}

任何帮助将不胜感激!

1 个答案:

答案 0 :(得分:2)

首先,你必须阅读正文然后解析它:

body, err := ioutil.ReadAll(resp.Body)
err = json.NewDecoder(body).Decode(&ip_response)
if err != nil {
    return Ip_response_success{}, err
}

另外,在go中,json解码器必须能够访问结构的字段。这意味着它们必须暴露在您的包裹之外。

这意味着您使用json注释来指定映射:

type Ip_response_success struct {
    As          string `json: "as"`
    City        string `json: "city"`
    Country     string `json: "country"`
    CountryCode string `json: "countryCode"`
    Isp         string `json: "isp"`
    Lat         float64 `json: "lat"`
    Lon         float64 `json: "lon"`
    Org         string `json: "org"`
    Query       string `json: "query"`
    Region      string `json: "region"`
    RegionName  string `json: "regionName"`
    Status      string `json: "status"`
    Timezone    string `json: "timezone"`
    Zip         string `json: "zip"`
}

另请注意,我根据服务器发送的数据将Lon / Lat类型更改为float64