高级主题
Serializer
登录后可跨设备保存划线和私人笔记登录
Serializer 是一个可扩展的接口,允许自定义数据与数据库之间的序列化和反序列化方式。
GORM 提供了一些默认的序列化器:json、gob、unixtime,以下是其使用方法的简单示例。
type User struct {
Name []byte `gorm:"serializer:json"`
Roles Roles `gorm:"serializer:json"`
Contracts map[string]interface{} `gorm:"serializer:json"`
JobInfo Job `gorm:"type:bytes;serializer:gob"`
CreatedTime int64 `gorm:"serializer:unixtime;type:time"`
}
type Roles []string
type Job struct {
Title string
Location string
IsIntern bool
}
createdAt := time.Date(2020, 1, 1, 0, 8, 0, 0, time.UTC)
data := User{
Name: []byte("jinzhu"),
Roles: []string{"admin", "owner"},
Contracts: map[string]interface{}{"name": "jinzhu", "age": 10},
CreatedTime: createdAt.Unix(),
JobInfo: Job{
Title: "Developer",
Location: "NY",
IsIntern: false,
},
}
DB.Create(&data)
var result User
DB.First(&result, "id = ?", data.ID)
DB.Where(User{Name: []byte("jinzhu")}).Take(&result)
注册序列化器
序列化器需要实现数据的序列化和反序列化方式,因此需要实现以下接口:
import "gorm.io/gorm/schema"
type SerializerInterface interface {
Scan(ctx context.Context, field *schema.Field, dst reflect.Value, dbValue interface{}) error
SerializerValuerInterface
}
type SerializerValuerInterface interface {
Value(ctx context.Context, field *schema.Field, dst reflect.Value, fieldValue interface{}) (interface{}, error)
}例如,默认的 JSONSerializer 实现如下:
type JSONSerializer struct {
}
func (JSONSerializer) Scan(ctx context.Context, field *schema.Field, dst reflect.Value, dbValue interface{}) (err error) {
fieldValue := reflect.New(field.FieldType)
if dbValue != nil {
var bytes []byte
switch v := dbValue.(type) {
case []byte:
bytes = v
case string:
bytes = []byte(v)
default:
return fmt.Errorf("failed to unmarshal JSONB value: %#v", dbValue)
}
err = json.Unmarshal(bytes, fieldValue.Interface())
}
field.ReflectValueOf(ctx, dst).Set(fieldValue.Elem())
return
}
func (JSONSerializer) Value(ctx context.Context, field *Field, dst reflect.Value, fieldValue interface{}) (interface{}, error) {
return json.Marshal(fieldValue)
}通过以下代码注册:
schema.RegisterSerializer("json", JSONSerializer{})注册序列化器后,可以通过 serializer 标签使用它,例如:
type User struct {
Name []byte `gorm:"serializer:json"`
}自定义序列化器类型
你可以通过标签使用已注册的序列化器,也可以创建一个实现上述 SerializerInterface 的自定义结构体,并直接将其用作字段类型,例如:
type EncryptedString string
func (es *EncryptedString) Scan(ctx context.Context, field *schema.Field, dst reflect.Value, dbValue interface{}) (err error) {
switch value := dbValue.(type) {
case []byte:
*es = EncryptedString(bytes.TrimPrefix(value, []byte("hello")))
case string:
*es = EncryptedString(strings.TrimPrefix(value, "hello"))
default:
return fmt.Errorf("unsupported data %#v", dbValue)
}
return nil
}
func (es EncryptedString) Value(ctx context.Context, field *schema.Field, dst reflect.Value, fieldValue interface{}) (interface{}, error) {
return "hello" + string(es), nil
}
type User struct {
gorm.Model
Password EncryptedString
}
data := User{
Password: EncryptedString("pass"),
}
DB.Create(&data)
var result User
DB.First(&result, "id = ?", data.ID)
DB.Where(User{Password: EncryptedString("pass")}).Take(&result)
评论
登录后参与评论
正在加载评论…
KnowForge