如何用Golang将指定格式字符串转为ISODate插入MongoDB?
解决自定义日期格式转MongoDB ISODate的问题
问题原因
Gin的ShouldBindJSON默认仅支持RFC3339等标准JSON日期格式,无法直接解析Mon Jan 30 2023 17:27:16 GMT+0200 (Eastern European Standard Time)这类非标准格式到primitive.DateTime,因此会返回Bad Request错误。
解决方案
方法一:自定义字段实现UnmarshalJSON接口
修改Transaction结构体的JSON解析逻辑,让它能识别目标日期格式:
import ( "encoding/json" "time" "go.mongodb.org/mongo-driver/bson/primitive" ) type Transaction struct { ID primitive.ObjectID `json:"id" bson:"_id"` Category primitive.ObjectID `bson:"category,omitempty"` Amount string `json:"amount" binding:"required"` Owner primitive.ObjectID `bson:"owner,omitempty"` Date primitive.DateTime `bson:"date" json:"date"` } // 自定义JSON反序列化方法,处理特殊日期格式 func (t *Transaction) UnmarshalJSON(data []byte) error { // 定义临时结构体,用string接收Date字段 type TempTx struct { ID primitive.ObjectID `json:"id"` Category primitive.ObjectID `json:"category,omitempty"` Amount string `json:"amount"` Owner primitive.ObjectID `json:"owner,omitempty"` Date string `json:"date"` } var temp TempTx if err := json.Unmarshal(data, &temp); err != nil { return err } // 按目标格式解析日期到time.Time layout := "Mon Jan 02 2006 15:04:05 GMT-0700 (Mountain Standard Time)" parsedTime, err := time.Parse(layout, temp.Date) if err != nil { return err } // 赋值并转换日期为primitive.DateTime(对应MongoDB的ISODate) t.ID = temp.ID t.Category = temp.Category t.Amount = temp.Amount t.Owner = temp.Owner t.Date = primitive.NewDateTimeFromTime(parsedTime) return nil }
之后绑定逻辑保持不变即可:
var transaction models.Transaction if err := c.ShouldBindJSON(&transaction); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } // 插入MongoDB时,Date会自动以ISODate格式存储 createdTransaction, createErr := handler.collection.InsertOne(handler.ctx, transaction)
方法二:临时结构体中转+手动转换
如果不想修改原结构体的解析逻辑,可以通过临时结构体完成绑定后再手动转换日期:
// 定义临时结构体 type TempTx struct { ID primitive.ObjectID `json:"id"` Category primitive.ObjectID `json:"category,omitempty"` Amount string `json:"amount" binding:"required"` Owner primitive.ObjectID `json:"owner,omitempty"` Date string `json:"date"` } var tempTx TempTx if err := c.ShouldBindJSON(&tempTx); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } // 解析日期 layout := "Mon Jan 02 2006 15:04:05 GMT-0700 (Mountain Standard Time)" parsedTime, err := time.Parse(layout, tempTx.Date) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "无效的日期格式"}) return } // 转换为正式Transaction结构体 transaction := models.Transaction{ ID: tempTx.ID, Category: tempTx.Category, Amount: tempTx.Amount, Owner: tempTx.Owner, Date: primitive.NewDateTimeFromTime(parsedTime), } // 插入MongoDB createdTransaction, createErr := handler.collection.InsertOne(handler.ctx, transaction)
关键注意事项
- 日期解析的
layout必须与传入的日期格式完全匹配,注意占位符对应关系(比如02代表两位日期,15代表24小时制小时)。 primitive.NewDateTimeFromTime()会将time.Time转换为MongoDB的ISODate类型,插入后会以标准ISODate格式存储。
内容的提问来源于stack exchange,提问作者Sasha Zoria
相关产品推荐
相关产品推荐

