Skip to content

Commit

Permalink
fix:serializer contain field panic (#5461)
Browse files Browse the repository at this point in the history
  • Loading branch information
wuweishuo committed Jun 25, 2022
1 parent a70af2a commit 3e6ab99
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 8 deletions.
2 changes: 1 addition & 1 deletion schema/field.go
Expand Up @@ -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,
}
},
}
Expand Down
43 changes: 36 additions & 7 deletions tests/serializer_test.go
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand All @@ -74,6 +100,7 @@ func TestSerializer(t *testing.T) {
Location: "Kenmawr",
IsIntern: false,
},
CustomSerializerString: "world",
}

if err := DB.Create(&data).Error; err != nil {
Expand All @@ -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)
Expand All @@ -109,6 +137,7 @@ func TestSerializerAssignFirstOrCreate(t *testing.T) {
Location: "Shadyside",
IsIntern: false,
},
CustomSerializerString: "world",
}

// first time insert record
Expand Down

0 comments on commit 3e6ab99

Please sign in to comment.