Golang mapstructure.Decode无法解析嵌套结构体字段求助
Golang使用mapstructure.Decode嵌套结构体时值丢失的问题解决
你遇到的不是mapstructure库的bug,而是使用方式未对齐mapstructure的默认匹配规则导致的。
问题原因
mapstructure默认使用结构体字段的驼峰名称去匹配输入map中的键名,但你通过json.Unmarshal解析得到的map里,键都是JSON原有的下划线/小写格式(比如url、state、pull_request),而你只给结构体字段添加了json标签,没有告诉mapstructure要参考这个标签进行匹配,导致字段无法对应,最终值为空。
解决方案
有两种方式可以解决这个问题:
方案1:给结构体字段补充mapstructure标签
直接在结构体字段上添加mapstructure标签,与json标签的键名保持一致,明确告诉mapstructure用哪个键匹配字段:
// Events represent repository events type Events []Event // Event represent a repository event type Event struct { ID string `json:"id" mapstructure:"id"` Type string `json:"type" mapstructure:"type"` Payload struct { PushID int `json:"push_id" mapstructure:"push_id"` Action string `json:"action" mapstructure:"action"` Size int `json:"size" mapstructure:"size"` PullRequest PullRequest `json:"pull_request" mapstructure:"pull_request"` } `json:"payload" mapstructure:"payload"` } // PullRequest represents pull request from github api type PullRequest struct { URL string `json:"url" mapstructure:"url"` State string `json:"state" mapstructure:"state"` }
方案2:配置解码器复用json标签
如果不想额外添加标签,可以通过DecodeConfig设置TagName为"json",让mapstructure直接使用json标签的规则进行字段匹配:
func main() { strg := `[{"created_at": "2024-01-19T05:32:35Z", "id": "34950536433", "payload": {"action": "reopened", "pull_request": {"additions": 1, "number": 23, "state": "open", "url": "test.com"}}, "public": true, "type": "PullRequestEvent"}]` evts := []interface{}{} events := Events{} err := json.Unmarshal([]byte(strg), &evts) if err != nil { panic(err) } config := &mapstructure.DecoderConfig{ TagName: "json", Result: &events, // 可选:忽略结构体中未定义的字段,避免解析报错 // IgnoreUntaggedFields: true, } decoder, err := mapstructure.NewDecoder(config) if err != nil { panic(err) } err = decoder.Decode(evts) if err != nil { panic(err) } fmt.Printf("%+v\n", events[0]) fmt.Printf("%+v\n", events[0].Payload.PullRequest) }
两种方案都能让你得到预期的输出,PullRequest的URL和State值会被正确解析。
内容的提问来源于stack exchange,提问作者jianliang wang
相关产品推荐
相关产品推荐

