feat: support gob serialize (#5108)

This commit is contained in:
jing1 2022-02-24 10:21:27 +08:00 committed by GitHub
parent 45ef1da7e4
commit 3741f258d0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 49 additions and 2 deletions

View File

@ -1,11 +1,12 @@
package schema package schema
import ( import (
"bytes"
"context" "context"
"database/sql" "database/sql"
"database/sql/driver" "database/sql/driver"
"encoding/gob"
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"reflect" "reflect"
"strings" "strings"
@ -32,6 +33,7 @@ func GetSerializer(name string) (serializer SerializerInterface, ok bool) {
func init() { func init() {
RegisterSerializer("json", JSONSerializer{}) RegisterSerializer("json", JSONSerializer{})
RegisterSerializer("unixtime", UnixSecondSerializer{}) RegisterSerializer("unixtime", UnixSecondSerializer{})
RegisterSerializer("gob", GobSerializer{})
} }
// Serializer field value serializer // Serializer field value serializer
@ -83,7 +85,7 @@ func (JSONSerializer) Scan(ctx context.Context, field *Field, dst reflect.Value,
case string: case string:
bytes = []byte(v) bytes = []byte(v)
default: 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()) err = json.Unmarshal(bytes, fieldValue.Interface())
@ -123,3 +125,33 @@ func (UnixSecondSerializer) Value(ctx context.Context, field *Field, dst reflect
} }
return 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
}

View File

@ -19,11 +19,20 @@ type SerializerStruct struct {
Name []byte `gorm:"json"` Name []byte `gorm:"json"`
Roles Roles `gorm:"serializer:json"` Roles Roles `gorm:"serializer:json"`
Contracts map[string]interface{} `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 CreatedTime int64 `gorm:"serializer:unixtime;type:time"` // store time in db, use int as field type
EncryptedString EncryptedString EncryptedString EncryptedString
} }
type Roles []string type Roles []string
type Job struct {
Title string
Number int
Location string
IsIntern bool
}
type EncryptedString string type EncryptedString string
func (es *EncryptedString) Scan(ctx context.Context, field *schema.Field, dst reflect.Value, dbValue interface{}) (err error) { 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}, Contracts: map[string]interface{}{"name": "jinzhu", "age": 10},
EncryptedString: EncryptedString("pass"), EncryptedString: EncryptedString("pass"),
CreatedTime: createdAt.Unix(), CreatedTime: createdAt.Unix(),
JobInfo: Job{
Title: "programmer",
Number: 9920,
Location: "Kenmawr",
IsIntern: false,
},
} }
if err := DB.Create(&data).Error; err != nil { if err := DB.Create(&data).Error; err != nil {