Initial encoder
This commit is contained in:
commit
844dfebed4
1 changed files with 94 additions and 0 deletions
94
serial.go
Normal file
94
serial.go
Normal file
|
@ -0,0 +1,94 @@
|
|||
package serial
|
||||
|
||||
import (
|
||||
"io"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type Encoder struct {
|
||||
w io.Writer
|
||||
wg sync.WaitGroup
|
||||
groups []string
|
||||
}
|
||||
|
||||
func (e *Encoder) Encode(entity interface{}) error {
|
||||
t := reflect.TypeOf(entity)
|
||||
v := reflect.ValueOf(entity)
|
||||
if err := e.encodeField(t, v, e.w); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (e *Encoder) encodeAny(entity interface{}, w io.Writer) error {
|
||||
t := reflect.TypeOf(entity)
|
||||
v := reflect.ValueOf(entity)
|
||||
first := true
|
||||
for i := 0; i < t.NumField(); i++ {
|
||||
f := t.Field(i)
|
||||
fv := v.Field(i)
|
||||
if gr, ok := f.Tag.Lookup("group"); ok {
|
||||
groups := strings.Split(gr, ",")
|
||||
name := f.Name
|
||||
if tname, ok := f.Tag.Lookup("json"); ok {
|
||||
name = tname
|
||||
}
|
||||
if name != "-" && e.intersect(groups, e.groups) {
|
||||
if !first {
|
||||
w.Write([]byte(`,`))
|
||||
}
|
||||
w.Write([]byte(`"` + name + `":`))
|
||||
e.encodeField(f.Type, fv, w)
|
||||
first = false
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Encoder) intersect(a []string, b []string) bool {
|
||||
for _, sa := range a {
|
||||
for _, sb := range b {
|
||||
if sa == sb {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (e *Encoder) encodeField(ft reflect.Type, v reflect.Value, w io.Writer) error {
|
||||
switch ft.Kind() {
|
||||
case reflect.Struct:
|
||||
w.Write([]byte("{"))
|
||||
if err := e.encodeAny(v.Interface(), w); err != nil {
|
||||
return err
|
||||
}
|
||||
w.Write([]byte("}"))
|
||||
case reflect.String:
|
||||
w.Write([]byte(`"` + v.String() + `"`))
|
||||
case reflect.Bool:
|
||||
if v.Bool() {
|
||||
w.Write([]byte("true"))
|
||||
} else {
|
||||
w.Write([]byte("false"))
|
||||
}
|
||||
case reflect.Int, reflect.Int32, reflect.Int64:
|
||||
w.Write([]byte(strconv.Itoa(int(v.Int()))))
|
||||
case reflect.Float32, reflect.Float64:
|
||||
w.Write([]byte(strconv.FormatFloat(v.Float(), 'f', -1, 64)))
|
||||
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Encoder) AddGroup(group string) *Encoder {
|
||||
e.groups = append(e.groups, group)
|
||||
return e
|
||||
}
|
||||
|
||||
func NewEncoder(w io.Writer) *Encoder {
|
||||
return &Encoder{w: w, groups: []string{}}
|
||||
}
|
Loading…
Reference in a new issue