Finish Serializer
This commit is contained in:
		
							parent
							
								
									5f6d85c00a
								
							
						
					
					
						commit
						a1dc940af3
					
				@ -432,7 +432,7 @@ func (field *Field) setupValuerAndSetter() {
 | 
				
			|||||||
			New: func() interface{} {
 | 
								New: func() interface{} {
 | 
				
			||||||
				return &Serializer{
 | 
									return &Serializer{
 | 
				
			||||||
					Field:     field,
 | 
										Field:     field,
 | 
				
			||||||
					Interface: reflect.New(reflect.ValueOf(field.Serializer).Type()).Interface().(SerializerInterface),
 | 
										Interface: reflect.New(reflect.Indirect(reflect.ValueOf(field.Serializer)).Type()).Interface().(SerializerInterface),
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@ -489,14 +489,14 @@ func (field *Field) setupValuerAndSetter() {
 | 
				
			|||||||
				return value, zero
 | 
									return value, zero
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			serializer, ok := value.(SerializerInterface)
 | 
								serializer, ok := value.(SerializerValuerInterface)
 | 
				
			||||||
			if !ok {
 | 
								if !ok {
 | 
				
			||||||
				serializer = field.Serializer
 | 
									serializer = field.Serializer
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			return Serializer{
 | 
								return Serializer{
 | 
				
			||||||
				Field:       field,
 | 
									Field:       field,
 | 
				
			||||||
				Interface:   serializer,
 | 
									Valuer:      serializer,
 | 
				
			||||||
				Destination: v,
 | 
									Destination: v,
 | 
				
			||||||
				Context:     ctx,
 | 
									Context:     ctx,
 | 
				
			||||||
				fieldValue:  value,
 | 
									fieldValue:  value,
 | 
				
			||||||
@ -564,6 +564,9 @@ func (field *Field) setupValuerAndSetter() {
 | 
				
			|||||||
			if reflectV.Kind() == reflect.Ptr {
 | 
								if reflectV.Kind() == reflect.Ptr {
 | 
				
			||||||
				if reflectV.IsNil() {
 | 
									if reflectV.IsNil() {
 | 
				
			||||||
					field.ReflectValueOf(ctx, value).Set(reflect.New(field.FieldType).Elem())
 | 
										field.ReflectValueOf(ctx, value).Set(reflect.New(field.FieldType).Elem())
 | 
				
			||||||
 | 
									} else if reflectV.Type().Elem().AssignableTo(field.FieldType) {
 | 
				
			||||||
 | 
										field.ReflectValueOf(ctx, value).Set(reflectV.Elem())
 | 
				
			||||||
 | 
										return
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					err = setter(ctx, value, reflectV.Elem().Interface())
 | 
										err = setter(ctx, value, reflectV.Elem().Interface())
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
@ -585,7 +588,7 @@ func (field *Field) setupValuerAndSetter() {
 | 
				
			|||||||
			if serializer, ok := v.(*Serializer); ok {
 | 
								if serializer, ok := v.(*Serializer); ok {
 | 
				
			||||||
				serializer.Interface.Scan(ctx, field, value, serializer.value)
 | 
									serializer.Interface.Scan(ctx, field, value, serializer.value)
 | 
				
			||||||
				fallbackSetter(ctx, value, serializer.Interface, field.Set)
 | 
									fallbackSetter(ctx, value, serializer.Interface, field.Set)
 | 
				
			||||||
				serializer.Interface = reflect.New(reflect.ValueOf(field.Serializer).Type()).Interface().(SerializerInterface)
 | 
									serializer.Interface = reflect.New(reflect.Indirect(reflect.ValueOf(field.Serializer)).Type()).Interface().(SerializerInterface)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			return nil
 | 
								return nil
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
				
			|||||||
@ -26,6 +26,7 @@ type FieldNewValuePool interface {
 | 
				
			|||||||
type Serializer struct {
 | 
					type Serializer struct {
 | 
				
			||||||
	Field       *Field
 | 
						Field       *Field
 | 
				
			||||||
	Interface   SerializerInterface
 | 
						Interface   SerializerInterface
 | 
				
			||||||
 | 
						Valuer      SerializerValuerInterface
 | 
				
			||||||
	Destination reflect.Value
 | 
						Destination reflect.Value
 | 
				
			||||||
	Context     context.Context
 | 
						Context     context.Context
 | 
				
			||||||
	value       interface{}
 | 
						value       interface{}
 | 
				
			||||||
@ -40,12 +41,17 @@ func (s *Serializer) Scan(value interface{}) error {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// Value implements driver.Valuer interface
 | 
					// Value implements driver.Valuer interface
 | 
				
			||||||
func (s Serializer) Value() (driver.Value, error) {
 | 
					func (s Serializer) Value() (driver.Value, error) {
 | 
				
			||||||
	return s.Interface.Value(s.Context, s.Field, s.Destination, s.fieldValue)
 | 
						return s.Valuer.Value(s.Context, s.Field, s.Destination, s.fieldValue)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// SerializerInterface serializer interface
 | 
					// SerializerInterface serializer interface
 | 
				
			||||||
type SerializerInterface interface {
 | 
					type SerializerInterface interface {
 | 
				
			||||||
	Scan(ctx context.Context, field *Field, dst reflect.Value, dbValue interface{}) error
 | 
						Scan(ctx context.Context, field *Field, dst reflect.Value, dbValue interface{}) error
 | 
				
			||||||
 | 
						SerializerValuerInterface
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SerializerValuerInterface serializer valuer interface
 | 
				
			||||||
 | 
					type SerializerValuerInterface interface {
 | 
				
			||||||
	Value(ctx context.Context, field *Field, dst reflect.Value, fieldValue interface{}) (interface{}, error)
 | 
						Value(ctx context.Context, field *Field, dst reflect.Value, fieldValue interface{}) (interface{}, error)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,9 +1,15 @@
 | 
				
			|||||||
package tests_test
 | 
					package tests_test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"bytes"
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"reflect"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"gorm.io/gorm"
 | 
						"gorm.io/gorm"
 | 
				
			||||||
 | 
						"gorm.io/gorm/schema"
 | 
				
			||||||
	. "gorm.io/gorm/utils/tests"
 | 
						. "gorm.io/gorm/utils/tests"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -11,11 +17,30 @@ type SerializerStruct struct {
 | 
				
			|||||||
	gorm.Model
 | 
						gorm.Model
 | 
				
			||||||
	Name            []byte `gorm:"json"`
 | 
						Name            []byte `gorm:"json"`
 | 
				
			||||||
	Roles           Roles  `gorm:"json"`
 | 
						Roles           Roles  `gorm:"json"`
 | 
				
			||||||
 | 
						EncryptedString EncryptedString
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Roles []string
 | 
					type Roles []string
 | 
				
			||||||
 | 
					type EncryptedString string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestSerializerJSON(t *testing.T) {
 | 
					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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Value implements serializer interface
 | 
				
			||||||
 | 
					func (es EncryptedString) Value(ctx context.Context, field *schema.Field, dst reflect.Value, fieldValue interface{}) (interface{}, error) {
 | 
				
			||||||
 | 
						return "hello" + string(es), nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestSerializer(t *testing.T) {
 | 
				
			||||||
	DB.Migrator().DropTable(&SerializerStruct{})
 | 
						DB.Migrator().DropTable(&SerializerStruct{})
 | 
				
			||||||
	if err := DB.Migrator().AutoMigrate(&SerializerStruct{}); err != nil {
 | 
						if err := DB.Migrator().AutoMigrate(&SerializerStruct{}); err != nil {
 | 
				
			||||||
		t.Fatalf("no error should happen when migrate scanner, valuer struct, got error %v", err)
 | 
							t.Fatalf("no error should happen when migrate scanner, valuer struct, got error %v", err)
 | 
				
			||||||
@ -24,6 +49,7 @@ func TestSerializerJSON(t *testing.T) {
 | 
				
			|||||||
	data := SerializerStruct{
 | 
						data := SerializerStruct{
 | 
				
			||||||
		Name:            []byte("jinzhu"),
 | 
							Name:            []byte("jinzhu"),
 | 
				
			||||||
		Roles:           []string{"r1", "r2"},
 | 
							Roles:           []string{"r1", "r2"},
 | 
				
			||||||
 | 
							EncryptedString: EncryptedString("pass"),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := DB.Create(&data).Error; err != nil {
 | 
						if err := DB.Create(&data).Error; err != nil {
 | 
				
			||||||
@ -31,7 +57,9 @@ func TestSerializerJSON(t *testing.T) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var result SerializerStruct
 | 
						var result SerializerStruct
 | 
				
			||||||
	DB.First(&result, data.ID)
 | 
						if err := DB.First(&result, data.ID).Error; err != nil {
 | 
				
			||||||
 | 
							t.Fatalf("failed to query data, got error %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	AssertEqual(t, result, data)
 | 
						AssertEqual(t, result, data)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user