Golang – 无法访问 []interface{} 中的 map

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

Golang - Cannot access map in []interface{}

问题

我已经使用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)
}

变量players的类型是[]interface{},内容是[map[personaname:Acidic]]

如何访问这个map呢?我尝试了players["personaname"],但似乎不起作用。有什么想法吗?

英文:

I have used json.Unmarshal and extracted json content. I then managed to get one layer deeper into the []interface{} by using the following code:

        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)
		}

Variable players' type is []interface {} and content is [map[personaname:Acidic]].

How do I access this map? I've tried players["personaname"] but that doesn't seem to work. Any ideas?

答案1

得分: 2

定义一个具有预期模式的结构类型将使您在获取其中的数据时更加方便:

package main

import "fmt"
import "encoding/json"

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() {
    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)
}

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

英文:

Defining a struct type with the expected schema will make your life easier when you want to get the data from it:

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

You can also create a new named type from time.Time for Timecreated and Lastlogoff with its own UnmarshalJSON function, and immediately convert it to time.Time using time.Unix()

答案2

得分: 0

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"])
}

希望对你有帮助!

英文:

Players is a JSON array. Thus you have to convert it to a slice of interface.

Then you can access any element of the slice and casting it to a map[string]interface{} type.

Here's the working example

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"])
}

huangapple
  • 本文由 发表于 2016年4月2日 18:27:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/36372082.html
匿名

发表评论

匿名网友

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

确定