将JSON数组反序列化为Go结构体(数组位于JSON字符串中间)。

3

我刚开始学习Go语言,正在使用一个天气API。我已经注释掉了引起错误的部分。我看到了很多类似问题的链接,但是没有一个链接与JSON字符串中间有数组的情况相同。我确信可以使用slice定义struct,但我无法得到正确的语法。下面是我卡住的地方:

package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
)

// WeatherData struct to collect data from the API call
type WeatherData struct {
    Wind Wind
    Sys  Sys
    // Weather Weather
    Name string `json:"name"`
}

////////////// ERROR when unmarshalling this struct /////////
// Weather provides basic weather info
// type Weather struct {
//  ID      int    `json:"id"`
//  Descrip string `json:"description"`
//  Icon    string `json:"icon"`
// }
/////////////////////////////////////////////////////////////

// Sys includes sunrise, sunset, country, etc.
type Sys struct {
    Country string `json:"country"`
}

// Wind struct to get specific wind characteristics
type Wind struct {
    Speed  float64 `json:"speed"`
    Degree float64 `json:"deg"`
    Gust   float64 `json:"gust"`
}

func main() {
    res, getErr := http.Get("http://api.openweathermap.org/data/2.5/weather?zip=REMOVED,us&appid=REMOVEDBUTWILLPOSTJSONData")
    if getErr != nil {
        log.Fatalln("http.Get error: ", getErr)
    }
    defer res.Body.Close()
    body, readErr := ioutil.ReadAll(res.Body)
    if readErr != nil {
        log.Fatalln("Read Error: ", readErr)
    }
//////////// UNABLE TO UNMARSHAL the array that passes through here ////
    var data WeatherData
    if err := json.Unmarshal(body, &data); err != nil {
        panic(err)
    }

    fmt.Println("Wind gusts: ", data.Wind.Gust)
    fmt.Println("Wind speed: ", data.Wind.Speed)
    fmt.Println("Wind degrees: ", data.Wind.Degree)

    fmt.Println("Country is: ", data.Sys.Country)
    fmt.Println("City is: ", data.Name)

///////////////// CAN'T ACCESS Description...or anything in Weather
// fmt.Println("Country is: ", data.Weather.Descrip) // cannot access due to this portion being inside an array

}



/////////////////THIS IS THE JSON DATA THAT IS AVAILABLE ///////////
{
  "coord": {
    "lon": -97.31,
    "lat": 32.94
  },
  "weather": [  // CAN'T ACCESS THIS CORRECTLY
    {
      "id": 800,
      "main": "Clear",
      "description": "clear sky",
      "icon": "01d"
    }
  ],
  "base": "stations",
  "main": {
    "temp": 306.46,
    "pressure": 1014,
    "humidity": 55,
    "temp_min": 306.15,
    "temp_max": 307.15
  },
  "visibility": 16093,
  "wind": {
    "speed": 5.1,
    "deg": 150,
    "gust": 7.2
  },
  "clouds": {
    "all": 1
  },
  "dt": 1499120100,
  "sys": {
    "type": 1,
    "id": 2597,
    "message": 0.0225,
    "country": "US",
    "sunrise": 1499081152,
    "sunset": 1499132486
  },
  "id": 0,
  "name": "Fort Worth",
  "cod": 200
}

我查看了一些类似问题的其他链接,但是这些解决方案并不完全适用于我的情况:https://stackoverflow.com/questions/40626125/golang-unmarshal-json-cannot-unmarshal-array-into-go-value-of-type-main-moni - Logan Wood
这个链接看起来最接近,但我不知道如何根据他们的解决方案描述创建自定义的非编组解码器... https://dev59.com/11gQ5IYBdhLWcg3wr17V - Logan Wood
更新:仍然没有生效,但我已经更改了: type WeatherData struct { Wind Wind Sys Sys Weather []Weather ////////// 这样做可以显示值,但好像失去了根据键标识值的能力 Name string json:"name" } - Logan Wood
1个回答

6

您需要在WeatherData中定义Weather结构的片段。

取消注释Weather结构,并将WeatherData结构更新为以下内容。

// WeatherData struct to collect data from the API call
type WeatherData struct {
    Wind    Wind      `json:"wind"`
    Sys     Sys       `json:"sys"`
    Weather []Weather `json:"weather"`
    Name    string    `json:"name"`
}

请查看示例代码:https://play.golang.org/p/4KFqRuxcx2

谢谢你的帮助,但我已经能够做到并获取数组数据块,但是我仍然无法调用类似data.Weather.Descrip这样的单个键/值,它返回未定义的错误。我还尝试添加类型[]map[string]interface{},它可以为我提供所有键/值对,但我仍然无法调用它们。您可以在此处查看我的更改:链接 - Logan Wood
你需要通过索引访问切片/数组的值,请参见此处:链接 - jeevatkm
它起作用了!非常感谢。我甚至已经通过索引0访问了整个内容,但没有意识到我可以在其上使用点符号表示法。再次感谢! - Logan Wood

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接