Go反序列化JSON时如何强制将非字符串值转为map[string]string的字符串值
解决方案
核心思路是自定义map类型实现json.Unmarshaler接口,重写反序列化逻辑,自动把JSON中任意类型的value转为字符串后存入map,不需要修改原JSON结构。
步骤1:自定义支持自动转字符串的map类型
import ( "encoding/json" "fmt" ) // 自定义StrMap,功能等价于map[string]string,支持反序列化时自动把任意JSON值转为字符串 type StrMap map[string]string // 实现json.Unmarshaler接口 func (m *StrMap) UnmarshalJSON(data []byte) error { // 先把JSON内容反序列化为值类型为interface{}的map,兼容任意类型的value var raw map[string]interface{} if err := json.Unmarshal(data, &raw); err != nil { return err } // 初始化map *m = make(StrMap, len(raw)) // 遍历所有键值对,把值统一转为字符串 for k, v := range raw { (*m)[k] = fmt.Sprintf("%v", v) } return nil }
步骤2:修改原结构体定义
注意你原来的Id字段的tag写错了,把jons改成json才能正常解析id字段:
type Data struct { Id int `json:"id"` Values StrMap `json:"values"` // 把原来的map[string]string换成自定义的StrMap }
测试验证
用你给出的示例JSON测试即可正常解析:
func main() { jsonStr := `{ "id": 1, "values": { "key1": "a string value", "key2": 7 } }` var d Data if err := json.Unmarshal([]byte(jsonStr), &d); err != nil { log.Fatal(err) } // 输出验证:d.Values["key2"] 就是字符串"7" fmt.Printf("%+v\n", d.Values) // 输出 map[key1:a string value key2:7] }
可选优化
如果需要自定义转换规则,比如布尔值转"1"/"0"、null转空字符串,可以在遍历raw时判断值的类型再做特殊处理:
for k, v := range raw { switch val := v.(type) { case float64: // JSON数字默认反序列化为float64类型 (*m)[k] = strconv.FormatFloat(val, 'f', -1, 64) case bool: (*m)[k] = strconv.FormatBool(val) case nil: (*m)[k] = "" default: (*m)[k] = fmt.Sprintf("%v", val) } }
内容的提问来源于stack exchange,提问作者Michael Anckaert
相关产品推荐
相关产品推荐

