1 Star 0 Fork 0

笑看风云/gocodes

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
MapToRef.go 8.03 KB
一键复制 编辑 原始数据 按行查看 历史
笑看风云 提交于 2022-06-28 13:09 +08:00 . 更新
package coderx
import (
"gitee.com/zhongguo168a/gocodes/datax/mapx"
"gitee.com/zhongguo168a/gocodes/datax/reflectx"
"gitee.com/zhongguo168a/gocodes/datax/schemax"
"gitee.com/zhongguo168a/gocodes/datax/schemax/basickind"
"gitee.com/zhongguo168a/gocodes/myx/errorx"
"strconv"
)
func NewMapToRef() (obj *MapToRef) {
obj = &MapToRef{}
return
}
type MapToRef struct {
//
source map[string]interface{}
// 忽视空值
// 空值不会输出到map中
ignoreNil bool
}
func (coder *MapToRef) Reset() {
coder.source = nil
coder.ignoreNil = false
}
func (coder *MapToRef) SetSource(source map[string]interface{}) *MapToRef {
coder.source = source
return coder
}
// Create 通过map创建一个对象
// map必须设置 key=_type value=string, value指向schemax注册的声明
func (coder *MapToRef) Create() (obj reflectx.IRefObject, err error) {
_type := mapx.String(coder.source, "_type")
if _type == "" {
err = errorx.New("_type not found")
return
}
schema := schemax.GetDeclByKey(_type)
if schema == nil {
err = errorx.New("schema not found: " + _type)
return
}
decl, ok := schema.(*schemax.ClassDecl)
if !ok {
err = errorx.New("decl not schemax.ClassDecl: " + _type)
return
}
reftype := reflectx.GetType(_type)
if reftype == nil {
err = errorx.New("reftype not found: " + decl.RefType())
return
}
obj = reftype.RefNew()
err = coder.fromMapObj(reftype, obj, coder.source, schema, "")
if err != nil {
err = errorx.Wrap(err, _type)
return
}
return
}
func (coder *MapToRef) Write(obj reflectx.IRefObject) (err error) {
schema := schemax.GetDeclByKey(obj.RefType())
if schema == nil {
return errorx.New("schema not found: " + obj.RefType())
}
reftype := reflectx.GetType(obj.RefType())
if reftype == nil {
err = errorx.New("reftype not found: " + obj.RefType())
return
}
return coder.fromMapObj(reftype, obj, coder.source, schema, "")
}
// keyMode 0-source的字段, 1-所有字段
func (coder *MapToRef) fromMapObj(reftype reflectx.IRefType, obj reflectx.IRefObject, smap map[string]interface{}, schema schemax.IDecl, paths string) (err error) {
var (
decl = schema.(*schemax.ClassDecl)
)
allfields := decl.GetAllField()
for _, field := range allfields {
fname := field.Name
alias := field.Alias()
mval, mhas := smap[alias]
if !mhas {
continue
}
fname = alias
switch ftyp := field.Type.(type) {
case *schemax.ClassType:
oval, isNil := reftype.(reflectx.IRefField).RefGet(obj, alias)
st, classerr := coder.fromMapClass(reftype, oval.(reflectx.IRefObject), isNil, mval, ftyp.Decl, paths+"/"+fname)
if classerr != nil {
return classerr
}
reftype.(reflectx.IRefField).RefSet(obj, alias, st)
case *schemax.ArrayType:
err = coder.fromMapSlice(reftype.(reflectx.IRefSlice), obj, mval, fname, ftyp, paths+"/"+fname)
if err != nil {
return
}
case *schemax.MapType:
err = coder.fromMapMap(reftype.(reflectx.IRefMap), obj, fname, mval, ftyp, paths+"/"+fname)
if err != nil {
return
}
case *schemax.EnumType:
st, classerr := coder.fromMapEnum(mval, ftyp.Decl, paths+"/"+fname)
if classerr != nil {
return classerr
}
reftype.(reflectx.IRefField).RefSet(obj, field.Name, st)
case *schemax.BasicType:
reftype.(reflectx.IRefField).RefSet(obj, field.Name, coder.fromMapBasic(mval, ftyp))
case *schemax.AnyType:
oval, isNil := reftype.(reflectx.IRefField).RefGet(obj, fname)
st, classerr := coder.fromMapAny(reftype, oval, isNil, mval, paths+"/"+fname)
if classerr != nil {
return classerr
}
reftype.(reflectx.IRefField).RefSet(obj, fname, st)
default:
}
}
return
}
func (coder *MapToRef) fromMapAny(reftype reflectx.IRefType, oany interface{}, isNil bool, sany interface{}, paths string) (st interface{}, err error) {
var (
decl string
smap map[string]interface{}
ismap bool
oval reflectx.IRefObject
)
if sany == nil { // 返回,并设置obj为nil
return
}
if oany == nil {
smap, ismap = sany.(map[string]interface{})
if ismap == false {
return
}
decl = mapx.String(smap, "_type")
if decl == "" {
st = sany
return
}
} else {
oval = oany.(reflectx.IRefObject)
decl = oval.RefType()
}
st, err = coder.fromMapClass(reftype, oval, isNil, sany.(map[string]interface{}), decl, paths)
if err != nil {
return
}
return
}
type TestClass1 struct {
}
func (t *TestClass1) RefType() string {
panic("implement me")
}
func (coder *MapToRef) fromMapClass(reftype reflectx.IRefType, oval reflectx.IRefObject, isNil bool, many interface{}, decl string, paths string) (rval reflectx.IRefObject, err error) {
if many == nil { // 设置为nil
return nil, nil
}
if isNil {
rval, err = reflectx.NewObject(decl)
if err != nil {
err = errorx.New(paths + ": new object " + decl + " : " + err.Error())
return
}
} else {
rval = oval
}
maptype := reflectx.GetType(decl)
if maptype == nil {
err = errorx.New(paths + ": reftype not found: " + oval.RefType())
return
}
stdesc := schemax.GetDeclByKey(decl)
err = coder.fromMapObj(maptype, rval, many.(map[string]interface{}), stdesc, paths)
return
}
func (coder *MapToRef) fromMapEnum(mval interface{}, decl string, paths string) (st interface{}, err error) {
idesc := schemax.GetDeclByKey(decl)
if idesc == nil {
err = errorx.New(paths + ": enum schema not found: " + decl)
return
}
enumdesc := idesc.(*schemax.EnumDecl)
st = enumdesc.ConvertToValue(mval)
return
}
func (coder *MapToRef) fromMapSlice(reftype reflectx.IRefSlice, obj reflectx.IRefObject, many interface{}, fname string, ftyp *schemax.ArrayType, paths string) (err error) {
if many == nil {
reftype.RefSet(obj, fname, reftype.RefSliceNew(fname, 0, 0))
return
}
marr := many.([]interface{})
mlen := len(marr)
mcap := cap(marr)
reftype.RefSet(obj, fname, reftype.RefSliceNew(fname, mlen, mcap))
if mlen == 0 {
return
}
switch etyp := ftyp.Elem.(type) {
case *schemax.ClassType:
for i := 0; i < len(marr); i++ {
mval := marr[i]
oval, isNil := reftype.RefSliceGet(obj, fname, i)
st, classerr := coder.fromMapClass(reftype, oval.(reflectx.IRefObject), isNil, mval, etyp.Decl, paths+"/"+strconv.Itoa(i))
if classerr != nil {
return classerr
}
reftype.RefSliceSet(obj, fname, i, st)
}
case *schemax.BasicType:
for i := 0; i < len(marr); i++ {
reftype.RefSliceSet(obj, fname, i, coder.fromMapBasic(marr[i], etyp))
}
case *schemax.EnumType:
for i := 0; i < len(marr); i++ {
mval := marr[i]
rval, classerr := coder.fromMapEnum(mval, etyp.Decl, paths+"/"+strconv.Itoa(i))
if classerr != nil {
return classerr
}
reftype.RefSliceSet(obj, fname, i, rval)
}
case *schemax.AnyType:
default:
err = errorx.New("decode array: not support type: " + etyp.String())
return
}
return
}
func (coder *MapToRef) fromMapMap(reftype reflectx.IRefMap, obj reflectx.IRefObject, fname string, many interface{}, ftyp *schemax.MapType, paths string) (err error) {
if many == nil { // 如果设置了nil
reftype.RefSet(obj, fname, nil)
return
}
mmap := many.(map[string]interface{})
_, isNil := reftype.RefGet(obj, fname)
if isNil {
// 创建
reftype.RefSet(obj, fname, reftype.RefMapNew(fname))
}
//
switch etyp := ftyp.Value.(type) {
case *schemax.ClassType:
for mkey, mval := range mmap {
oval, onil := reftype.RefMapGet(obj, fname, mkey)
st, classerr := coder.fromMapClass(reftype, oval.(reflectx.IRefObject), onil, mval, etyp.Decl, paths+"/"+mkey)
if classerr != nil {
return classerr
}
reftype.RefMapSet(obj, fname, mkey, st)
}
case *schemax.BasicType:
for mkey, mval := range mmap {
reftype.RefMapSet(obj, fname, mkey, coder.fromMapBasic(mval, etyp))
}
case *schemax.EnumType:
for mkey, mval := range mmap {
rval, classerr := coder.fromMapEnum(mval, etyp.Decl, paths+"/"+mkey)
if classerr != nil {
return classerr
}
reftype.RefMapSet(obj, fname, mkey, rval)
}
default:
err = errorx.New(paths + ": decode array: not support type: " + etyp.String())
return
}
return
}
func (coder *MapToRef) fromMapBasic(mval interface{}, ftyp *schemax.BasicType) interface{} {
return basickind.ConvertKindToStruct(ftyp.Kind, mval)
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/zhongguo168a/gocodes.git
git@gitee.com:zhongguo168a/gocodes.git
zhongguo168a
gocodes
gocodes
4da1013f7e88

搜索帮助