diff --git a/schema/field.go b/schema/field.go index 981f56f2a..d4dfbd6f7 100644 --- a/schema/field.go +++ b/schema/field.go @@ -950,7 +950,7 @@ func (field *Field) setupNewValuePool() { New: func() interface{} { return &serializer{ Field: field, - Serializer: reflect.New(reflect.Indirect(reflect.ValueOf(field.Serializer)).Type()).Interface().(SerializerInterface), + Serializer: field.Serializer, } }, } diff --git a/tests/serializer_test.go b/tests/serializer_test.go index ee14841a9..80e015ffa 100644 --- a/tests/serializer_test.go +++ b/tests/serializer_test.go @@ -16,13 +16,14 @@ import ( type SerializerStruct struct { gorm.Model - Name []byte `gorm:"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"` // store time in db, use int as field type - UpdatedTime *int64 `gorm:"serializer:unixtime;type:time"` // store time in db, use int as field type - EncryptedString EncryptedString + Name []byte `gorm:"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"` // store time in db, use int as field type + UpdatedTime *int64 `gorm:"serializer:unixtime;type:time"` // store time in db, use int as field type + CustomSerializerString string `gorm:"serializer:custom"` + EncryptedString EncryptedString } type Roles []string @@ -52,7 +53,32 @@ func (es EncryptedString) Value(ctx context.Context, field *schema.Field, dst re return "hello" + string(es), nil } +type CustomSerializer struct { + prefix []byte +} + +func NewCustomSerializer(prefix string) *CustomSerializer { + return &CustomSerializer{prefix: []byte(prefix)} +} + +func (c *CustomSerializer) Scan(ctx context.Context, field *schema.Field, dst reflect.Value, dbValue interface{}) (err error) { + switch value := dbValue.(type) { + case []byte: + err = field.Set(ctx, dst, bytes.TrimPrefix(value, c.prefix)) + case string: + err = field.Set(ctx, dst, strings.TrimPrefix(value, string(c.prefix))) + default: + err = fmt.Errorf("unsupported data %#v", dbValue) + } + return err +} + +func (c *CustomSerializer) Value(ctx context.Context, field *schema.Field, dst reflect.Value, fieldValue interface{}) (interface{}, error) { + return fmt.Sprintf("%s%s", c.prefix, fieldValue), nil +} + func TestSerializer(t *testing.T) { + schema.RegisterSerializer("custom", NewCustomSerializer("hello")) DB.Migrator().DropTable(&SerializerStruct{}) if err := DB.Migrator().AutoMigrate(&SerializerStruct{}); err != nil { t.Fatalf("no error should happen when migrate scanner, valuer struct, got error %v", err) @@ -74,6 +100,7 @@ func TestSerializer(t *testing.T) { Location: "Kenmawr", IsIntern: false, }, + CustomSerializerString: "world", } if err := DB.Create(&data).Error; err != nil { @@ -90,6 +117,7 @@ func TestSerializer(t *testing.T) { } func TestSerializerAssignFirstOrCreate(t *testing.T) { + schema.RegisterSerializer("custom", NewCustomSerializer("hello")) DB.Migrator().DropTable(&SerializerStruct{}) if err := DB.Migrator().AutoMigrate(&SerializerStruct{}); err != nil { t.Fatalf("no error should happen when migrate scanner, valuer struct, got error %v", err) @@ -109,6 +137,7 @@ func TestSerializerAssignFirstOrCreate(t *testing.T) { Location: "Shadyside", IsIntern: false, }, + CustomSerializerString: "world", } // first time insert record