英文:
In Go Language, how do I unmarshal json to array of object?
问题
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"].(int32)
monster.MonsterId = v["monster-id"].(int32)
monster.SkillLevel = v["skill-level"].(int32)
monster.AimerId = v["aimer-id"].(int32)
mc.Pool[i] = *monster
i++
}
}
英文:
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().
答案1
得分: 19
这段代码有很多错误。首先,json不是有效的json。你在顶层对象的键值对之间缺少了逗号。我为你添加了逗号并进行了漂亮的打印:
{
"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
}
}
你下一个问题(你提到的问题)是m := data.(map[string]interface{})
使m
成为了map[string]interface{}
。这意味着当你在range循环中索引它时,类型是interface{}
。你需要再次使用类型断言v.(map[string]interface{})
,然后每次从map中读取时都进行类型断言。
我还注意到你下一个尝试mc.Pool[i] = monster
,当i是int类型而mc.Pool是map[string]Monster类型时。int不是该map的有效键。
你的数据看起来非常固定,所以我建议让unmarshal为你完成大部分工作。你可以提供一个map[string]Monster给它,而不是map[string]interface{}。
这是一个快速的示例。除了改变unmarshalling的工作方式之外,我还添加了一个错误返回。错误返回对于查找错误很有用。这个错误返回告诉我你的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)
}
我在goplay上发布了一个可工作的示例:http://play.golang.org/p/4EaasS2VLL
英文:
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
答案2
得分: 0
稍微偏离一边 - 当你需要一个映射时,你要求一个对象数组
如果你需要一个数组(实际上是一个切片)
http://ioblocks.blogspot.com/2014/09/loading-arrayslice-of-objects-from-json.html
英文:
Slightly off to one side - you asked for an array of objects when you needed a map
If you need an array (actually a slice)
http://ioblocks.blogspot.com/2014/09/loading-arrayslice-of-objects-from-json.html
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论