golang下如何仿django實現serializer,十分適用!
阿新 • • 發佈:2018-11-10
如何實現serializer用golang
對返回的model進行 django裡的 toRepresentation()操作(update,pop,picked)
目前只針對json編碼方式,其他方式待跟進
serializer實現如下:
package serializer
import (
"encoding/json"
"github.com/fwhezfwhez/errorx"
)
// A block type aims to mapper the origin struct to a map[string]interface{}
// For Instance:
// struct{
// Name string
// Age int
// }{
// Name: "fwhezfwhez",
// Age: 9,
// }
// The Block of the struct would be a map[string]interface{} {"name":"ft","age":9}
//
type Block map[string]interface{}
func (b *Block) Update(key string, value interface{})*Block{
(*b)[key] = value
return b
}
func (b *Block) Pop(key string )*Block{
delete(*b, key)
return b
}
type SerializerI interface{
Serialize(dest interface{},f func(b Block)(func(b Block)Block,[]string))([]byte,error)
}
// a json serializer realization
type JsonSerializer struct{
}
func (s JsonSerializer) Serialize(dest interface{},f func(b Block)(func(b Block) Block,[]string))([]byte,error){
//1. transfer the struct to a map
var m = make(Block,0)
buf, er :=json.Marshal(dest)
if er!=nil {
return nil, errorx.New(er)
}
er = json.Unmarshal(buf,&m)
if er!=nil {
return nil, errorx.New(er)
}
//2. handle picked fields into the map
blockHandler,picked :=f(m)
//2.1 get filtered fields , get all fields if picked is nil or len=0
var filtPicked Block
if picked ==nil || len(picked) ==0{
filtPicked = m
}else{
filtPicked = make(Block,0)
for _,v :=range picked{
vm,ok := m[v]
if !ok {
continue
}
filtPicked[v] = vm
}
}
//2.2 change fields with the updated and popped staff
buf, er = json.Marshal(blockHandler(filtPicked))
if er != nil {
return nil, errorx.Wrap(er)
}
return buf, nil
}
如何使用
go get github.com/fwhezfwhez/go-serializer
package main
import (
"encoding/json"
"fmt"
"github.com/fwhezfwhez/go-serializer"
"time"
)
type User struct {
serializer.SerializerI
Name string `json:"name"`
Age int `json:"age"`
Salary float64 `json:"salary"`
CreatedAt time.Time `json:"created_at"`
}
func (u User) ToRepresentation(f func(serializer.Block) (func(b serializer.Block) serializer.Block, []string)) ([]byte, error) {
return u.Serialize(u, f)
}
func main() {
u := User{
SerializerI: serializer.JsonSerializer{},
Name: "ft2",
Age: 9,
Salary: 1000,
CreatedAt: time.Now(),
}
buf, er := u.ToRepresentation(func(m serializer.Block) (func(b serializer.Block) serializer.Block, []string) {
// abandon the 'Salary' field,use 'pick:= []string(nil)' to stand for all picked
pick := []string{"age", "created", "name"}
handler := func(b serializer.Block) serializer.Block {
// update
b.Update("question", "why?")
b.Update("location", "china")
// pop
b.Pop("location")
// rewrite
b.Update("created_at", u.CreatedAt.Format("2006-01-02 15:04:05"))
return b
}
return handler, pick
})
if er != nil {
fmt.Println(er.Error())
return
}
// the result of buf is a json []byte
fmt.Println(string(buf))
// if you want a further operator to the json map,get it by:
var m map[string]interface{}
json.Unmarshal(buf, &m)
fmt.Println(m)
}
result:
{"age":9,"created_at":"2018-10-15 09:55:24","name":"ft2","question":"why?"}
map[age:9 created_at:2018-10-15 09:55:24 name:ft2 question:why?]