Golang插入interface数据到MongoDB时整数字段被存为Double如何解决
问题根因
Go标准库encoding/json默认将JSON中的所有数值类型反序列化到interface{}类型变量时,都会统一转换为float64类型。你代码中解析得到的data map里的number1本身就已经是float64类型,因此插入MongoDB后会被存储为Double类型。
解决方案
针对非结构化JSON数据的场景,最简便的适配方案是使用json.Decoder的UseNumber()选项处理解析逻辑:
- 该选项会将JSON数值解析为
json.Number类型(本质是保留原始数值格式的字符串) - MongoDB官方Go驱动会自动识别
json.Number的实际格式,整数会映射为Int类型存储,浮点数会映射为Double类型存储,无需额外手动转换
修改后的核心代码
首先需要导入bytes包,然后替换原有JSON解析逻辑:
package main import ( "bytes" "context" "encoding/json" "fmt" "log" "time" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" ) func main() { mongoURI := fmt.Sprintf("mongodb://%s:%s@%s:%d", "root", "root", "localhost", 27017) ctxtimeout, cancelCtx := context.WithTimeout(context.Background(), 60*time.Second) mongoConnection, err := mongo.NewClient(options.Client().ApplyURI(mongoURI)) if err != nil { log.Fatal(err.Error()) } defer cancelCtx() err = mongoConnection.Connect(ctxtimeout) if err != nil { log.Fatal(err.Error()) } defer mongoConnection.Disconnect(ctxtimeout) mongoDatabase := mongoConnection.Database("dbname") mongoCollection := mongoDatabase.Collection("posts") str := `{ "number1": 10, "number2": 20.1 }` var data map[string]interface{} // 替换原有json.Unmarshal逻辑 decoder := json.NewDecoder(bytes.NewBuffer([]byte(str))) decoder.UseNumber() err = decoder.Decode(&data) if err != nil { log.Fatal(err.Error()) } reMar, _ := json.Marshal(data) fmt.Println(string(reMar)) mongoCollection.InsertOne(ctxtimeout, data) }
其他可选方案
- 如果你需要更强的类型控制,可以遍历解析后的
map[string]interface{},对所有float64类型的值做校验:如果float64(int64(val)) == val,就将其转换为int64类型后再插入Mongo - 如果数据字段结构可预估,直接定义对应结构体并指定字段类型,将JSON反序列化到结构体实例后再插入,可完全保证类型匹配
内容的提问来源于stack exchange,提问作者Sippkron Raksakiart
相关产品推荐
相关产品推荐

