Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Go Language, how do I unmarshal json to array of object?

Tags:

go

I have the following JSON, and I want to parse it into array of class:

{
    "1001": {"level":10, "monster-id": 1001, "skill-level": 1, "aimer-id": 301}
    "1002": {"level":12, "monster-id": 1002, "skill-level": 1, "aimer-id": 302}
    "1003": {"level":16, "monster-id": 1003, "skill-level": 2, "aimer-id": 303}
}

Here is what i am trying to do but failed:

type Monster struct {
    MonsterId  int32
    Level      int32
    SkillLevel int32
    AimerId    int32
}


type MonsterCollection struct {
    Pool map[string]Monster
}

func (mc *MonsterCollection) FromJson(jsonStr string) {
    var data interface{}
    b := []byte(jsonStr)
    err := json.Unmarshal(b, &data)
    if err != nil {
        return
    }

    m := data.(map[string]interface{})

    i := 0
    for k, v := range m {

        monster := new(Monster)
        monster.Level = v["level"]
        monster.MonsterId = v["monster-id"]
        monster.SkillLevel = v["skill-level"]
        monster.AimerId = v["aimer-id"]

        mc.Pool[i] = monster
        i++
    }

}

The compiler complain about the v["level"] << invalid operation. index of type interface().

like image 837
Nick Avatar asked Jun 05 '13 04:06

Nick


People also ask

How do you Unmarshal a JSON?

To parse JSON, we use the Unmarshal() function in package encoding/json to unpack or decode the data from JSON to a struct. Unmarshal parses the JSON-encoded data and stores the result in the value pointed to by v. Note: If v is nil or not a pointer, Unmarshal returns an InvalidUnmarshalError.

How does JSON Unmarshal work in Golang?

Marshal function, will take JSON data and translate it back into Go data. You provide json. Unmarshal with the JSON data as well as the Go variable to put the unmarshalled data into and it will either return an error value if it's unable to do it, or a nil error value if it succeeded.

How do you Unmarshal in Go?

Unmarshal is the contrary of marshal. It allows you to convert byte data into the original data structure. In go, unmarshaling is handled by the json. Unmarshal() method.

How do I write JSON data to a file in Golang?

Reading and Writing JSON Files in Go It is actually pretty simple to read and write data to and from JSON files using the Go standard library. For writing struct types into a JSON file we have used the WriteFile function from the io/ioutil package. The data content is marshalled/encoded into JSON format.


1 Answers

This code has many errors in it. To start with, the json isn't valid json. You are missing the commas in between key pairs in your top level object. I added the commas and pretty printed it for you:

{
   "1001":{
      "level":10,
      "monster-id":1001,
      "skill-level":1,
      "aimer-id":301
   },
   "1002":{
      "level":12,
      "monster-id":1002,
      "skill-level":1,
      "aimer-id":302
   },
   "1003":{
      "level":16,
      "monster-id":1003,
      "skill-level":2,
      "aimer-id":303
   }
}

Your next problem (the one you asked about) is that m := data.(map[string]interface{}) makes m a map[string]interface{}. That means when you index it such as the v in your range loop, the type is interface{}. You need to type assert it again with v.(map[string]interface{}) and then type assert each time you read from the map.


I also notice that you next attempt mc.Pool[i] = monster when i is an int and mc.Pool is a map[string]Monster. An int is not a valid key for that map.


Your data looks very rigid so I would make unmarshall do most of the work for you. Instead of providing it a map[string]interface{}, you can provide it a map[string]Monster.

Here is a quick example. As well as changing how the unmarshalling works, I also added an error return. The error return is useful for finding bugs. That error return is what told me you had invalid json.

type Monster struct {
    MonsterId  int32 `json:"monster-id"`
    Level      int32 `json:"level"`
    SkillLevel int32 `json:"skill-level"`
    AimerId    int32 `json:"aimer-id"`
}

type MonsterCollection struct {
    Pool map[string]Monster
}

func (mc *MonsterCollection) FromJson(jsonStr string) error {
    var data = &mc.Pool
    b := []byte(jsonStr)
    return json.Unmarshal(b, data)
}

I posted a working example to goplay: http://play.golang.org/p/4EaasS2VLL

like image 194
Stephen Weinberg Avatar answered Sep 17 '22 17:09

Stephen Weinberg