将嵌套的 JSON 响应反序列化为嵌套的结构体。

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

Unmarshaling nest JSON response into nested struct

问题

这是我调用的Web API返回的示例JSON:

{
"Ability1": "有毒烟雾",
"AbilityId1": 7812,
"AttackSpeed": 0.86,
"Cons": "",
"HP5PerLevel": 0.47,
"Health": 360,
"Speed": 350,
"abilityDescription1": {
"itemDescription": {
"cooldown": "12s",
"cost": "60/70/80/90/100",
"description": "阿格尼在地面目标位置召唤一团有毒烟雾,每秒造成伤害。将阿格尼的任何技能释放到烟雾中会引爆气体,使半径内的所有敌人昏迷。",
"menuitems": [
{
"description": "技能:",
"value": "地面目标"
},
{
"description": "影响:",
"value": "敌人"
},
{
"description": "伤害:",
"value": "魔法"
},
{
"description": "半径:",
"value": "20"
}
],
"rankitems": [
{
"description": "每次伤害:",
"value": "10/20/30/40/50 (+5%魔法强度)"
},
{
"description": "烟雾持续时间:",
"value": "10秒"
},
{
"description": "昏迷持续时间:",
"value": "1秒"
}
],
"secondaryDescription": ""
}
},
"abilityDescription5": {
"itemDescription": {
"cooldown": "",
"cost": "",
"description": "在进行4次基础攻击后,阿格尼将获得一个增益效果。在下一次释放火焰波或火雨时,被这些技能击中的所有敌人还会被点燃,每0.5秒造成伤害,持续3秒。",
"menuitems": [
{
"description": "影响:",
"value": "敌人"
},
{
"description": "伤害:",
"value": "魔法"
}
],
"rankitems": [
{
"description": "每次伤害:",
"value": "5 (+10%魔法强度)"
}
],
"secondaryDescription": ""
}
},
"basicAttack": {
"itemDescription": {
"cooldown": "",
"cost": "",
"description": "",
"menuitems": [
{
"description": "伤害:",
"value": "34 + 1.5/等级 (+20%魔法强度)"
},
{
"description": "进展:",
"value": "无"
}
],
"rankitems": [],
"secondaryDescription": ""
}
},
"id": 1737,
"ret_msg": null
}

这是我定义的结构体:

type God struct {
Ability1 string
Ability2 string
Ability3 string
Ability4 string
Ability5 string
AbilityId1 int
AbilityId2 int
AbilityId3 int
AbilityId4 int
AbilityId5 int
Attack_speed float64
Attack_speed_per_level float64
Cons string
Hp5_per_level float64
Health int
Health_per_five int
Health_per_level int
Item1 string
Item2 string
Item3 string
Item4 string
Item5 string
Item6 string
Item7 string
Item8 string
Item9 string
ItemId1 int
ItemId2 int
ItemId3 int
ItemId4 int
ItemId5 int
ItemId6 int
ItemId7 int
ItemId8 int
ItemId9 int
Lore string
Mp5_per_level float64
Magic_protection int
Magic_protection_per_level int
Mana int
Mana_per_five float64
Mana_per_level int
Name string
On_free_rotation string
Pantheon string
Physical_power int
Physical_power_per_level int
Physical_protection int
Physical_protection_per_level float64
Pros string
Roles string
Speed int
Title string
Type string
Abilitydescription1 struct {
Item_description struct {
Cooldown string
Cost string
Description string
Menu_items struct {
Description string
Value string
}
Rank_items struct {
Description string
Value string
}
Secondary_description string
}
}
Ability_description2 struct {
Item_description struct {
Cooldown string
Cost string
Description string
Menu_items struct {
Description string
Value string
}
Rank_items struct {
Description string
Value string
}
Secondary_description string
}
}
Ability_description3 struct {
Item_description struct {
Cooldown string
Cost string
Description string
Menu_items struct {
Description string
Value string
}
Rank_items struct {
Description string
Value string
}
Secondary_description string
}
}
Ability_description4 struct {
Item_description struct {
Cooldown string
Cost string
Description string
Menu_items struct {
Description string
Value string
}
Rank_items struct {
Description string
Value string
}
Secondary_description string
}
}
Ability_description5 struct {
Item_description struct {
Cooldown string
Cost string
Description string
Menu_items struct {
Description string
Value string
}
Rank_items struct {
Description string
Value string
}
Secondary_description string
}
}
Basic_attack struct {
Item_description struct {
cooldown string
cost string
description string
Menu_items struct {
Description string
Value string
}
Rank_items struct {
Description string
Value string
}
Secondary_description string
}
}
Id int
Ret_msg string
}

这是我如何将JSON响应解组为结构体数组的方法:

var gods []God
json.Unmarshal(jsonResponse, &gods)
return gods

除了abilityDescription1(2,3,4,5)和该结构体内的所有内容外,其他都可以正确解组。有什么建议吗?

英文:

Here's the sample JSON returning from the web API I'm invoking:

{
    "Ability1": "Noxious Fumes",
    "AbilityId1": 7812,
    "AttackSpeed": 0.86,
    "Cons": "",
    "HP5PerLevel": 0.47,
    "Health": 360,
    "Speed": 350,
    "abilityDescription1": {
      "itemDescription": {
        "cooldown": "12s",
        "cost": "60/70/80/90/100",
        "description": "Agni summons a cloud of noxious fumes at his ground target location, doing damage every second. Firing any of Agni's abilities into the fumes detonates the gas, stunning all enemies in the radius.",
        "menuitems": [
          {
            "description": "Ability:",
            "value": "Ground Target"
          },
          {
            "description": "Affects:",
            "value": "Enemy"
          },
          {
            "description": "Damage:",
            "value": "Magical"
          },
          {
            "description": "Radius:",
            "value": "20"
          }
        ],
        "rankitems": [
          {
            "description": "Damage per Tick:",
            "value": "10/20/30/40/50 (+5% of your magical power)"
          },
          {
            "description": "Fumes Duration:",
            "value": "10s"
          },
          {
            "description": "Stun Duration:",
            "value": "1s"
          }
        ],
        "secondaryDescription": ""
      }
    },
    "abilityDescription5": {
      "itemDescription": {
        "cooldown": "",
        "cost": "",
        "description": "After hitting with 4 basic attacks, Agni will gain a buff. On the next cast of Flame Wave or Rain Fire, all enemies hit by those abilities will be additionally set ablaze, taking damage every .5s for 3s.",
        "menuitems": [
          {
            "description": "Affects:",
            "value": "Enemy"
          },
          {
            "description": "Damage:",
            "value": "Magical"
          }
        ],
        "rankitems": [
          {
            "description": "Damage per Tick:",
            "value": "5 (+10% of your magical power)"
          }
        ],
        "secondaryDescription": ""
      }
    },
    "basicAttack": {
      "itemDescription": {
        "cooldown": "",
        "cost": "",
        "description": "",
        "menuitems": [
          {
            "description": "Damage:",
            "value": "34 + 1.5/Lvl (+20% of Magical Power)"
          },
          {
            "description": "Progression:",
            "value": "None"
          }
        ],
        "rankitems": [],
        "secondaryDescription": ""
      }
    },
    "id": 1737,
    "ret_msg": null
  }

And my struct:

type God struct {
	Ability1                      string
	Ability2                      string
	Ability3                      string
	Ability4                      string
	Ability5                      string
	AbilityId1                    int
	AbilityId2                    int
	AbilityId3                    int
	AbilityId4                    int
	AbilityId5                    int
	Attack_speed                  float64
	Attack_speed_per_level        float64
	Cons                          string
	Hp5_per_level                 float64
	Health                        int
	Health_per_five               int
	Health_per_level              int
	Item1                         string
	Item2                         string
	Item3                         string
	Item4                         string
	Item5                         string
	Item6                         string
	Item7                         string
	Item8                         string
	Item9                         string
	ItemId1                       int
	ItemId2                       int
	ItemId3                       int
	ItemId4                       int
	ItemId5                       int
	ItemId6                       int
	ItemId7                       int
	ItemId8                       int
	ItemId9                       int
	Lore                          string
	Mp5_per_level                 float64
	Magic_protection              int
	Magic_protection_per_level    int
	Mana                          int
	Mana_per_five                 float64
	Mana_per_level                int
	Name                          string
	On_free_rotation              string
	Pantheon                      string
	Physical_power                int
	Physical_power_per_level      int
	Physical_protection           int
	Physical_protection_per_level float64
	Pros                          string
	Roles                         string
	Speed                         int
	Title                         string
	Type                          string
	Abilitydescription1           struct {
		Item_description struct {
			Cooldown    string
			Cost        string
			Description string
			Menu_items  struct {
				Description string
				Value       string
			}
			Rank_items struct {
				Description string
				Value       string
			}
			Secondary_description string
		}
	}
	Ability_description2 struct {
		Item_description struct {
			Cooldown    string
			Cost        string
			Description string
			Menu_items  struct {
				Description string
				Value       string
			}
			Rank_items struct {
				Description string
				Value       string
			}
			Secondary_description string
		}
	}
	Ability_description3 struct {
		Item_description struct {
			Cooldown    string
			Cost        string
			Description string
			Menu_items  struct {
				Description string
				Value       string
			}
			Rank_items struct {
				Description string
				Value       string
			}
			Secondary_description string
		}
	}
	Ability_description4 struct {
		Item_description struct {
			Cooldown    string
			Cost        string
			Description string
			Menu_items  struct {
				Description string
				Value       string
			}
			Rank_items struct {
				Description string
				Value       string
			}
			Secondary_description string
		}
	}
	Ability_description5 struct {
		Item_description struct {
			Cooldown    string
			Cost        string
			Description string
			Menu_items  struct {
				Description string
				Value       string
			}
			Rank_items struct {
				Description string
				Value       string
			}
			Secondary_description string
		}
	}
	Basic_attack struct {
		Item_description struct {
			cooldown    string
			cost        string
			description string
			Menu_items  struct {
				Description string
				Value       string
			}
			Rank_items struct {
				Description string
				Value       string
			}
			Secondary_description string
		}
	}
	Id      int
	Ret_msg string
}

Here's how I unmarshal the JSON response into the struct array:

var gods []God
json.Unmarshal(jsonResponse, &gods)
return gods

Everything is marshalling properly except the abilityDescription1(2,3,4,5) and everything within that struct.

Any suggestions?

答案1

得分: 1

使用结构标签将JSON字段名映射到结构字段名。

你的许多结构字段都是小写的,因此无法被编码/解码包(encoding/json package)访问或编组。请查看http://golang.org/pkg/reflect/#StructTag(JSON包将“Description”与“description”匹配,即小写已经匹配)。

为了提高可读性和添加标签的能力,最好将结构拆分为单独的项,然后进行嵌入。你有一些重复使用Rank_items的情况,而你可以定义它一次,然后根据需要进行嵌入:

例如:

   Basic_attack struct {
        ItemDescription ItemDesc `json:"itemDescription"`
        Menu []MenuItems `json:"menuitems"`
        Rank []RankItems  `json:"rankitems"`
   }

   ItemDesc struct {
        Cooldown    string `json:"cooldown"`
        Cost        string `json:"cost"`
        Description string `json:"description"`
        Menu        []MenuItems `json:"menuitems"`
        ...
   }

   MenuItems  struct {
            Description string 
            Value       string
  }

   RankItems struct {
                Description string
                Value       string
   }
英文:

Use struct tags to map JSON field names to struct field names.

Many of your struct fields are lowercase and therefore unexported, which means the encoding/json package cannot access/marshal into them. Take a look at http://golang.org/pkg/reflect/#StructTag (the JSON package will match "Description" with "description", though - i.e. lower-case is already a match)

You are also better off (for readability/ability to add tags) splitting your structs into separate items, and then embedding them. You have cases where you're repeating Rank_items, whereas you could define it once and then embed it as needed:

e.g.

   Basic_attack struct {
        ItemDescription ItemDesc `json:"itemDescription"`
        Menu []MenuItems `json:"menuitems"`
        Rank []RankItems  `json:"rankitems"`
   }

   ItemDesc struct {
        Cooldown    string `json:"cooldown"`
        Cost        string `json:"cost"`
        Description string `json:"description"`
        Menu        []MenuItems `json:"menuitems"`
        ...
   }

   MenuItems  struct {
            Description string 
            Value       string
  }

   RankItems struct {
                Description string
                Value       string
   }

huangapple
  • 本文由 发表于 2014年2月20日 08:38:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/21895743.html
匿名

发表评论

匿名网友

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

确定