Go中JSON反序列化数组元素类型不一致问题
问题:JSON数组解析后元素类型不一致的原因
我有如下JSON文件:
{ "Path":"", "Tables":[ { "name":"testTable", "content":{ "c1":[ 1, 2, 3 ] } } ] }
将其解析为以下Go结构体:
type Database struct { Path string `json:"Path"` Tables []Table `json:"Tables"` } type Table struct { Name string `json:"name"` Content map[Column][]any `json:"content"` }
(注:使用any类型存储数据库中的任意值)
遍历
content中的[]any打印类型时,发现除最后一个值为int外,其余均为float64,c1的输出如下:
+1.000000e+000 +2.000000e+000 3
以下是可复现的示例代码:
// You can edit this code! // Click here and start typing. package main import ( "encoding/json" ) type Column string type Table struct { Name string `json:"name"` Content map[Column][]any `json:"content"` } type Database struct { Path string `json:"Path"` Tables []Table `json:"Tables"` } func (t *Table) Select(columns ...Column) Table { var newTable Table newTable.Content = make(map[Column][]any, 0) for _, c := range columns { if t.Content[c] != nil { newTable.Content[c] = t.Content[c] } } return newTable } func (d *Database) Get(table string) *Table { for _, t := range d.Tables { if t.Name == table { return &t } } return nil } func main() { jsonStr := `{"Path":"","Tables":[{"name":"testTable","content":{"c1":[1,2,3,3],"c2":[2,2,1,1],"c3":[3,3,2,2]}}]}` var db Database if err := json.Unmarshal([]byte(jsonStr), &db); err != nil { panic("error") } t := db.Get("testTable") ts := t.Select("c1", "c2") for _, v := range ts.Content { for _, v2 := range v { //println(v2.(int)) - panic //println(v2.(float64)) - panic switch v2.(type) { case int: println(v2.(int)) break default: println(v2.(float64)) } } } }
原因分析
这是Go标准库encoding/json的数值解析优化逻辑导致的:
- JSON本身没有区分整数和浮点数的类型,所有数值统一属于JSON number类型。
encoding/json在解析JSON数组到[]any时,会先尝试将元素解析为float64,但如果遇到重复的整数值,会触发内存优化:将后续重复的相同整数值复用Go预定义的int类型常量(比如int(3)),以此减少内存分配。- 你示例里
c1数组最后两个元素都是3,所以第二个3会被解析为int类型,而前面的1、2因为只出现一次,保持float64类型。
验证这个逻辑很简单:把数组改成[1,1,2,2],你会看到前两个1里,第二个是int;后两个2里,第二个是int。
解决办法
如果需要统一的数值类型,有两种方案:
- 方案一:将
Content的类型改为map[Column][]float64,强制所有数值解析为浮点数,之后按需转换为整数。 - 方案二:自定义JSON解析逻辑,在解析数组时统一将数值转为
int或float64,避免类型不一致。
内容的提问来源于stack exchange,提问作者0x3alex
相关产品推荐
相关产品推荐

