Go语言如何正确反序列化键为int类型的嵌套map
Go 中嵌套 map[int] 结构的 JSON 全层级反序列化方案
问题根源
JSON 标准规范明确要求对象的键必须为字符串类型,Go 标准库
encoding/json的默认反序列化逻辑有如下规则:
- 显式声明目标变量为
map[int]interface{}类型时,顶层键会自动尝试将 JSON 的字符串键转换为 int 类型- 对于嵌套的
interface{}类型值,遇到 JSON 对象时默认会反序列化为map[string]interface{},不会自动做 int 键转换,这就是嵌套层键为 string 类型的根本原因。
解决方案:自定义反序列化逻辑实现全层级 int 键转换
你可以通过实现 json.Unmarshaler 接口,递归处理所有层级的 map 键转换,示例实现如下:
package main import ( "encoding/json" "fmt" "strconv" ) // 自定义 int 键 map 类型,实现 json.Unmarshaler 接口 type IntKeyMap map[int]interface{} func (m *IntKeyMap) UnmarshalJSON(data []byte) error { // 先按默认规则反序列化为 string 键 map var raw map[string]interface{} if err := json.Unmarshal(data, &raw); err != nil { return err } *m = make(IntKeyMap) // 遍历处理所有键值对 for kStr, v := range raw { // 字符串键转 int kInt, err := strconv.Atoi(kStr) if err != nil { return fmt.Errorf("非法int格式键: %s", kStr) } // 递归处理嵌套对象 switch nestedVal := v.(type) { case map[string]interface{}: var nestedMap IntKeyMap nestedData, _ := json.Marshal(nestedVal) if err := json.Unmarshal(nestedData, &nestedMap); err != nil { return err } (*m)[kInt] = nestedMap default: (*m)[kInt] = nestedVal } } return nil } func main() { buf := []byte(`{"1":"one","2":{"3":"three"}}`) var obj IntKeyMap if err := json.Unmarshal(buf, &obj); err != nil { panic(err) } // 输出验证:main.IntKeyMap{1:"one", 2:main.IntKeyMap{3:"three"}} fmt.Printf("%#v\n", obj) }
注意事项
- 如果业务场景中存在非 int 格式的字符串键,可根据需求调整错误处理逻辑,比如忽略非法键、保留为 string 类型
- 上述递归实现对任意深度的嵌套结构都适用,所有层级的 map 都会自动转为
IntKeyMap类型,键均为 int 类型
内容的提问来源于stack exchange,提问作者user17503953
相关产品推荐
相关产品推荐

