备注: gorm
自定义json格式
文章目录 遇到问题分析原因解决方案step 1step 2
遇到问题
在使用gorm
包定义的数据库的结构如下:
type SystemParameter struct {
GlobalSslEnable bool `json:"globalSslEnable,omitempty"`
GlobalSslVisitedHosts []string `json:"globalSslVisitedHosts,omitempty"`
UserInfoInterfaceURL string `json:"userInfoInterfaceURL,omitempty"`
}
对数据库创建mysql数据的时候报错:(sql: converting argument $1 type: unsupported type []string, a slice of string)
分析原因mysql中不支持[]string
类型的数据,不可以直接在结构体中定义[]string
类型。
mysql中支持的数据结构类型有如下几种:
数值类型:TINYINT、SMALLINT、MEDIUMINT、INT或INTEGER、BIGINT、FLOAT、DOUBLE、DECIMAL;
日期和时间类型:DATE、TIME、YEAR、DATETIME、TIMESTAMP;
字符串类型:CHAR、VARCHAR、TINYBLOB、TINYTEXT、BLOB、TEXT、MEDIUMBLOB、MEDIUMTEXT、LONGBLOB、LONGTEXT;
因此mysql中并不支持[]string
类型的数据,不能直接在结构体中直接定义,为了能够在数据库中存储[]string
类型的数据,需要讲结构体中这个类型的数据进行封装,转换成为mysql支持的数据类型。
基于gorm
库的特性,可以通过自定义JSON
类型将数据传入,因此解决步骤一共分为两步:
[]string
类型编码为JSON
类型数据;step 2:自定义JSON
类型数据,使得gorm
可以支持,可以参考GORM-自定义数据类型;
step 1
首先将结构体中数据类型定义改为一个新的自定义类型,NullGlobalSslVisitedHosts
用于判断GlobalSslVisitedHosts
是否为空。
// 修改types.go
type SystemParameter struct {
GlobalSslEnable bool `json:"globalSslEnable,omitempty"`
GlobalSslVisitedHosts NullGlobalSslVisitedHosts `json:"globalSslVisitedHosts,omitempty"`
UserInfoInterfaceURL string `json:"userInfoInterfaceURL,omitempty"`
}
type NullGlobalSslVisitedHosts struct {
GlobalSslVisitedHosts GlobalSslVisitedHosts
Valid bool
}
type GlobalSslVisitedHosts []string
// GormDataType return the gorm data type
func (GlobalSslVisitedHosts) GormDataType() string {
return "json"
}
在gorm
的依赖库中(地址为:gorm.io/gorm/schema/field.go
)修改,增加上面刚定义的函数
// 修改gorm.io/gorm/schema/field.go
if dataTyper, ok := fieldValue.Interface().(GormDataTypeInterface); ok {
field.DataType = DataType(dataTyper.GormDataType())
}
在gorm
的依赖库中(地址为:gorm.io/gorm/schema/interfaces.go
) 增加定义的接口
// 修改gorm.io/gorm/schema/interfaces.go
type GormDataTypeInterface interface {
GormDataType() string
}
step 2
自定义一个JSON
类型,可以参考GORM-自定义数据类型
// 修改types.go
// Scan implements the Scanner interface.
func (n *NullGlobalSslVisitedHosts) Scan(value interface{}) error {
if value == nil {
n.GlobalSslVisitedHosts, n.Valid = GlobalSslVisitedHosts{}, false
return nil
}
n.Valid = true
var t GlobalSslVisitedHosts
err := t.Scan(value)
if err != nil {
return err
}
n.GlobalSslVisitedHosts, n.Valid = t, true
return nil
}
// Value implements the driver Valuer interface.
func (n NullGlobalSslVisitedHosts) Value() (driver.Value, error) {
if !n.Valid {
return nil, nil
}
return n.GlobalSslVisitedHosts.Value()
}
func (i *GlobalSslVisitedHosts) Scan(value interface{}) error {
bytesValue, ok := value.([]byte)
if !ok {
return errors.New(fmt.Sprint("Failed to unmarshal GlobalSslVisitedHosts value:", value))
}
return json.Unmarshal(bytesValue, i)
}
// Value return json value, implement driver.Valuer interface
func (i GlobalSslVisitedHosts) Value() (driver.Value, error) {
return json.Marshal(i)
}
func (v NullGlobalSslVisitedHosts) MarshalJSON() ([]byte, error) {
if v.Valid {
return json.Marshal(v.GlobalSslVisitedHosts)
} else {
return json.Marshal(nil)
}
}
func (v *NullGlobalSslVisitedHosts) UnmarshalJSON(data []byte) error {
// Unmarshalling into a pointer will let us detect null
var x *GlobalSslVisitedHosts
if err := json.Unmarshal(data, &x); err != nil {
return err
}
if x != nil {
v.Valid = true
v.GlobalSslVisitedHosts = *x
} else {
v.Valid = false
}
return nil
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)