You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 12:05:28