1 Star 1 Fork 1

wuuder/go-yaml

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
decode.go 3.66 KB
一键复制 编辑 原始数据 按行查看 历史
wuuder 提交于 2022-05-27 16:57 . yaml
package yaml
import (
"fmt"
"github.com/pkg/errors"
"reflect"
"strings"
)
type decode struct {
t reflect.Type
v reflect.Value
}
// unmarshal decodes the document found within the in byte slice
func (d *decode) unmarshal(dest interface{}, cp map[string]interface{}, params ...string) error {
d.t = reflect.TypeOf(dest).Elem()
d.v = reflect.ValueOf(dest).Elem()
if params == nil {
c, ok := cp[strings.ToLower(d.t.Name())]
if !ok {
return errors.Errorf("No related parameters found:%s ", strings.ToLower(d.t.Name()))
}
return d.sUnmarshal(c.(map[string]interface{}))
}
var (
c interface{}
ok bool
)
for _, param := range params {
c, ok = cp[param]
if !ok {
return errors.Errorf("No related parameters found:%s ", param)
}
if reflect.TypeOf(c).Kind() == reflect.Map {
cp = c.(map[string]interface{})
}
}
if reflect.ValueOf(c).Type() == d.t {
d.v.Set(reflect.ValueOf(c))
return nil
}
k := d.v.Type().Kind()
switch k {
case reflect.Interface:
d.v.Set(reflect.ValueOf(c))
case reflect.Struct:
return d.sUnmarshal(cp)
case reflect.Slice:
d.deslice(d.v, c.([]interface{}))
return nil
case reflect.Map:
d.demap(d.v, c.(map[string]interface{}))
return nil
}
return nil
}
func (d *decode) sUnmarshal(cp map[string]interface{}) error {
if d.t.Kind() != reflect.Struct {
return errors.Errorf("No related structures found:%s ", strings.ToLower(d.t.Name()))
}
b := cp
for i := 0; i < d.t.NumField(); i++ {
field := d.t.Field(i)
name := d.getTagName(field)
if val, ok := b[name]; ok {
f := d.v.Field(i)
if reflect.ValueOf(val).Type() == field.Type {
d.v.Field(i).Set(reflect.ValueOf(val))
continue
}
k := f.Type().Kind()
switch k {
case reflect.Struct:
d.destruct(f, val)
continue
case reflect.Slice:
d.deslice(f, val.([]interface{}))
continue
case reflect.Map:
d.demap(f, val.(map[string]interface{}))
continue
}
}
}
return nil
}
func (d *decode) getTagName(value reflect.StructField) string {
name := value.Tag.Get("json")
if value.Tag.Get("json") == "" {
name = strings.ToLower(value.Name)
}
return name
}
// destruct struct custom type conversion
func (d *decode) destruct(value reflect.Value, mp interface{}) {
m := mp.(map[string]interface{})
structField := value.Type()
for i := 0; i < structField.NumField(); i++ {
v := value.Field(i)
name := d.getTagName(structField.Field(i))
if val, ok := m[name]; ok {
// 判断是否还是结构体
if v.Type().Kind() == reflect.Struct {
d.destruct(value.Field(i), val)
continue
}
v.Set(reflect.ValueOf(val))
}
}
}
// deslice slice custom type conversion
func (d *decode) deslice(value reflect.Value, li []interface{}) {
switch value.Type().String() {
case "[]int":
var list []int
for _, l := range li {
if reflect.TypeOf(l).String() == "int" {
list = append(list, l.(int))
}
}
value.Set(reflect.ValueOf(list))
case "[]string":
var list []string
for _, l := range li {
if reflect.TypeOf(l).String() == "string" {
list = append(list, l.(string))
}
}
value.Set(reflect.ValueOf(list))
}
}
// deslice map custom type conversion
func (d *decode) demap(value reflect.Value, mp map[string]interface{}) {
switch value.Type().String() {
case "map[string]string":
mm := make(map[string]string)
for i, m := range mp {
fmt.Println(i, m)
fmt.Println(reflect.TypeOf(i).String())
if reflect.TypeOf(m).String() == "string" {
mm[i] = m.(string)
}
}
value.Set(reflect.ValueOf(mm))
case "map[string]int":
mm := make(map[string]int)
for i, m := range mp {
if reflect.TypeOf(m).String() == "int" {
mm[i] = m.(int)
}
}
value.Set(reflect.ValueOf(mm))
}
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/wuuder/go-yaml.git
[email protected]:wuuder/go-yaml.git
wuuder
go-yaml
go-yaml
master

搜索帮助