0

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
  • 1
    could you post the expected JSON content? I'm afraid you asserted wrong thing into wrong type. Commented Apr 2, 2016 at 11:09

2 Answers 2

2

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

Sign up to request clarification or add additional context in comments.

2 Comments

I personally prefer to create structs to strongly type my data, though it is more work.
There are tools now to auto generate struct types from json and it's not that hard to Google for them. It shouldn't take long to come to understand map[string]interface{} is the wrong type of laziness. The interface{} object you end up with is so much more difficult to deal with.
0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.