将 json 数组解组为 go struct(数组在 JSON 字符串的中间

Posted

技术标签:

【中文标题】将 json 数组解组为 go struct(数组在 JSON 字符串的中间【英文标题】:unmarshal json array into go struct (array is in the middle of the JSON string 【发布时间】:2017-07-04 00:58:04 【问题描述】:

我是 Go 新手。我正在使用天气 API。我已经注释掉了导致错误的部分。我已经看到其他几个有类似问题的链接,但是它们似乎都没有在 JSON 字符串的中间有数组。我确信有一种方法可以用切片定义结构。我似乎无法获得允许它的语法。这是我卡住的地方:

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

【问题讨论】:

Additional Links 我看过一个非常相似的问题,但解决方案不太适合我的场景:***.com/questions/40626125/… 这个链接看起来最接近,但我不知道如何根据他们的解决方案描述创建自定义解组器...***.com/questions/42377989/… 更新:它仍然无法正常工作,但我已更改:type WeatherData struct Wind Wind Sys Sys Weather []Weather ////////// this results in the values showing up, but I seem to lose the ability to identify the values based on their keys Name string json:"name"` ` 【参考方案1】:

您必须在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 之类的东西调用单个键/值。描述它返回未定义的错误。我还尝试添加类型 []map[string]interface,它可以为我提供所有键/值对,但我仍然无法调用它们。你可以在这里看到我的变化:link 您需要通过索引访问切片/数组值,请参见此处:link。 有效!非常感谢。我什至已经通过索引 0 访问整个事物,但没有意识到我可以在此之上做点符号。再次感谢!

以上是关于将 json 数组解组为 go struct(数组在 JSON 字符串的中间的主要内容,如果未能解决你的问题,请参考以下文章

json 错误,无法将对象解组为 Go 值

json:无法将字符串解组为 MyMap.map 类型的 Go 值

部分 JSON 在 Go 中解组为地图

无法将字符串解组为 int64 类型的 Go 值

Akka HTTP:如何将 Json 格式响应解组为域对象

部分JSON解组到Go中的地图中