将 JSON 数组解组为 Go 结构体(数组位于 JSON 字符串的中间)

huangapple go评论107阅读模式
英文:

unmarshal json array into go struct (array is in the middle of the JSON string

问题

我是你的中文翻译助手,以下是你提供的代码的翻译:

package main

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

// WeatherData 结构体用于存储从 API 调用中获取的数据
type WeatherData struct {
	Wind Wind
	Sys  Sys
	// Weather Weather
	Name string `json:"name"`
}

////////////// 在解组这个结构体时出现错误 ///////////
// Weather 提供基本的天气信息
// type Weather struct {
// 	ID      int    `json:"id"`
// 	Descrip string `json:"description"`
// 	Icon    string `json:"icon"`
// }
/////////////////////////////////////////////////////////

// Sys 包括日出、日落、国家等信息
type Sys struct {
	Country string `json:"country"`
}

// Wind 结构体用于获取具体的风力特征
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)
	}
	//////////// 无法解组通过这里的数组 //////////
	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)

	///////////// 无法访问 Description...或者 Weather 中的任何内容
	// fmt.Println("Country is:", data.Weather.Descrip) // 由于该部分位于数组中,无法访问

}

这是你提供的可用的 JSON 数据:

{
  "coord": {
    "lon": -97.31,
    "lat": 32.94
  },
  "weather": [  // 无法正确访问这里
    {
      "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
}

希望对你有帮助!

英文:

I am new to Go. I am working with a weather API. I have commented out the sections that cause the error. I have seen several other links that have a similar problem, however none of them seem to have the array in the middle of the JSON string. I'm sure there is a way to define the struct with a slice. I can't seem to get get the syntax to allow it. Here is where I'm stuck:

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
}

答案1

得分: 5

你必须在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

英文:

You have to define slice of Weather struct in WeatherData.

Uncomment Weather struct and update WeatherData struct to following.

// 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"`
}

Please have a look on example code: https://play.golang.org/p/4KFqRuxcx2

huangapple
  • 本文由 发表于 2017年7月4日 08:58:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/44895535.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定