【问题标题】:Golang - Cannot access map in []interface{}Golang - 无法在 []interface{} 中访问地图
【发布时间】:2016-07-22 04:33:46
【问题描述】:

我使用了json.Unmarshal 并提取了 json 内容。然后,我设法通过使用以下代码使[]interface{} 更深入一层:

        response, err := http.Get("http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?key=2B2A0C37AC20B5DC2234E579A2ABB11C&steamids=76561198132612090")
        content, err := ioutil.ReadAll(response.Body)
        defer response.Body.Close()
        if err != nil {
            panic(0)
        }

        var decoded map[string]interface{}
        if err := json.Unmarshal(content, &decoded); err != nil {
            panic(0)
        }

        players := decoded["response"].(map[string]interface{})["players"]
        if err != nil {
            panic(0)
        }

变量播放器类型为[]interface {},内容为[map[personaname:Acidic]]

如何访问此地图?我试过players["personaname"] 但这似乎不起作用。有什么想法吗?

【问题讨论】:

  • 您能发布预期的 JSON 内容吗?恐怕您将错误的东西断言为错误的类型。

标签: json dictionary go interface


【解决方案1】:

使用预期架构定义结构类型将使您在想要从中获取数据时更轻松:

package main

import "fmt"

//import "net/http"
//import "io/ioutil"
import "encoding/json"

// you don't need to define everything, only what you need
type Player struct {
    Steamid                  string
    Communityvisibilitystate int
    Personaname              string
    Lastlogoff               int64 // time.Unix(Lastlogoff, 0)
    Profileurl               string
    Avatar                   string
    Avatarmedium             string
    Avatarfull               string
    Personastate             int
    Realname                 string
    Primaryclanid            string
    Timecreated              int64 // time.Unix(Timecreated, 0)
    Personastateflags        int
    //Loccountrycode           string // e.g. if you don't need this
}

func main() {
    /*response, err := http.Get("http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?key=2B2A0C37AC20B5DC2234E579A2ABB11C&steamids=76561198132612090")
    if err != nil {
        panic(err)
    }
    content, err := ioutil.ReadAll(response.Body)
    defer response.Body.Close()
    if err != nil {
        panic(0)
    }*/
    content := []byte(`{
    "response": {
        "players": [
            {
                "steamid": "76561198132612090",
                "communityvisibilitystate": 3,
                "profilestate": 1,
                "personaname": "Acidic",
                "lastlogoff": 1459489924,
                "profileurl": "http://steamcommunity.com/id/ari9/",
                "avatar": "https://steamcdn-a.akamaihd.net/steamcommunity/public/images/avatars/bc/bc50a4065c31c606e51dfad329341b2d1f1ac4d3.jpg",
                "avatarmedium": "https://steamcdn-a.akamaihd.net/steamcommunity/public/images/avatars/bc/bc50a4065c31c606e51dfad329341b2d1f1ac4d3_medium.jpg",
                "avatarfull": "https://steamcdn-a.akamaihd.net/steamcommunity/public/images/avatars/bc/bc50a4065c31c606e51dfad329341b2d1f1ac4d3_full.jpg",
                "personastate": 3,
                "realname": "Ari Seyhun",
                "primaryclanid": "103582791440552060",
                "timecreated": 1397199406,
                "personastateflags": 0,
                "loccountrycode": "TR"
            }
        ]

    }
}`)

    var decoded struct {
        Response struct {
            Players []Player
        }
    }
    if err := json.Unmarshal(content, &decoded); err != nil {
        panic(err)
    }

    fmt.Printf("%#v\n", decoded.Response.Players)
}

http://play.golang.org/p/gVPRwLFunF

您还可以使用自己的UnmarshalJSON 函数从time.TimeTimecreatedLastlogoff 创建一个新的命名类型,并使用time.Unix() 立即将其转换为time.Time

【讨论】:

  • 我个人更喜欢创建结构来强类型化我的数据,虽然这需要更多的工作。
  • 现在有一些工具可以从 json 自动生成结构类型,谷歌搜索它们并不难。很快就会明白 map[string]interface{} 是错误的懒惰类型。你最终得到的 interface{} 对象更难处理。
【解决方案2】:

Players 是一个 JSON 数组。因此,您必须将其转换为界面切片。

然后您可以访问切片的任何元素并将其转换为 map[string]interface{} 类型。

这是工作示例

package main

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

func main() {
    response, err := http.Get("http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?key=2B2A0C37AC20B5DC2234E579A2ABB11C&steamids=76561198132612090")
    content, err := ioutil.ReadAll(response.Body)
    defer response.Body.Close()
    if err != nil {
        panic(0)
    }

    var decoded map[string]interface{}
    if err := json.Unmarshal(content, &decoded); err != nil {
        panic(0)
    }

    players := decoded["response"].(map[string]interface{})["players"]
    if err != nil {
        panic(0)
    }

    sliceOfPlayers := players.([]interface{})
    fmt.Println((sliceOfPlayers[0].(map[string]interface{}))["personaname"])
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-05-02
    • 1970-01-01
    • 1970-01-01
    • 2016-03-08
    • 1970-01-01
    • 1970-01-01
    • 2021-06-22
    相关资源
    最近更新 更多