feat: support gob serialize
This commit is contained in:
		
							parent
							
								
									b1201fce4e
								
							
						
					
					
						commit
						6c7b46a231
					
				@ -1,11 +1,12 @@
 | 
			
		||||
package schema
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"context"
 | 
			
		||||
	"database/sql"
 | 
			
		||||
	"database/sql/driver"
 | 
			
		||||
	"encoding/gob"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"strings"
 | 
			
		||||
@ -32,6 +33,7 @@ func GetSerializer(name string) (serializer SerializerInterface, ok bool) {
 | 
			
		||||
func init() {
 | 
			
		||||
	RegisterSerializer("json", JSONSerializer{})
 | 
			
		||||
	RegisterSerializer("unixtime", UnixSecondSerializer{})
 | 
			
		||||
	RegisterSerializer("gob", GobSerializer{})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Serializer field value serializer
 | 
			
		||||
@ -83,7 +85,7 @@ func (JSONSerializer) Scan(ctx context.Context, field *Field, dst reflect.Value,
 | 
			
		||||
		case string:
 | 
			
		||||
			bytes = []byte(v)
 | 
			
		||||
		default:
 | 
			
		||||
			return errors.New(fmt.Sprint("Failed to unmarshal JSONB value:", dbValue))
 | 
			
		||||
			return fmt.Errorf("failed to unmarshal JSONB value: %#v", dbValue)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		err = json.Unmarshal(bytes, fieldValue.Interface())
 | 
			
		||||
@ -123,3 +125,33 @@ func (UnixSecondSerializer) Value(ctx context.Context, field *Field, dst reflect
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GobSerializer gob serializer
 | 
			
		||||
type GobSerializer struct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Scan implements serializer interface
 | 
			
		||||
func (GobSerializer) Scan(ctx context.Context, field *Field, dst reflect.Value, dbValue interface{}) (err error) {
 | 
			
		||||
	fieldValue := reflect.New(field.FieldType)
 | 
			
		||||
 | 
			
		||||
	if dbValue != nil {
 | 
			
		||||
		var bytesValue []byte
 | 
			
		||||
		switch v := dbValue.(type) {
 | 
			
		||||
		case []byte:
 | 
			
		||||
			bytesValue = v
 | 
			
		||||
		default:
 | 
			
		||||
			return fmt.Errorf("failed to unmarshal gob value: %#v", dbValue)
 | 
			
		||||
		}
 | 
			
		||||
		decoder := gob.NewDecoder(bytes.NewBuffer(bytesValue))
 | 
			
		||||
		err = decoder.Decode(fieldValue.Interface())
 | 
			
		||||
	}
 | 
			
		||||
	field.ReflectValueOf(ctx, dst).Set(fieldValue.Elem())
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Value implements serializer interface
 | 
			
		||||
func (GobSerializer) Value(ctx context.Context, field *Field, dst reflect.Value, fieldValue interface{}) (interface{}, error) {
 | 
			
		||||
	buf := new(bytes.Buffer)
 | 
			
		||||
	err := gob.NewEncoder(buf).Encode(fieldValue)
 | 
			
		||||
	return buf.Bytes(), err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -19,11 +19,20 @@ type SerializerStruct struct {
 | 
			
		||||
	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
 | 
			
		||||
	EncryptedString EncryptedString
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Roles []string
 | 
			
		||||
 | 
			
		||||
type Job struct {
 | 
			
		||||
	Title    string
 | 
			
		||||
	Number   int
 | 
			
		||||
	Location string
 | 
			
		||||
	IsIntern bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type EncryptedString string
 | 
			
		||||
 | 
			
		||||
func (es *EncryptedString) Scan(ctx context.Context, field *schema.Field, dst reflect.Value, dbValue interface{}) (err error) {
 | 
			
		||||
@ -56,6 +65,12 @@ func TestSerializer(t *testing.T) {
 | 
			
		||||
		Contracts:       map[string]interface{}{"name": "jinzhu", "age": 10},
 | 
			
		||||
		EncryptedString: EncryptedString("pass"),
 | 
			
		||||
		CreatedTime:     createdAt.Unix(),
 | 
			
		||||
		JobInfo: Job{
 | 
			
		||||
			Title:    "programmer",
 | 
			
		||||
			Number:   9920,
 | 
			
		||||
			Location: "Kenmawr",
 | 
			
		||||
			IsIntern: false,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := DB.Create(&data).Error; err != nil {
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user