gitee.com/zhongguo168a/gocodes@v0.0.0-20230609140523-e1828349603f/datax/coderx/MapToRef.go (about) 1 package coderx 2 3 import ( 4 "gitee.com/zhongguo168a/gocodes/datax/mapx" 5 "gitee.com/zhongguo168a/gocodes/datax/reflectx" 6 "gitee.com/zhongguo168a/gocodes/datax/schemax" 7 "gitee.com/zhongguo168a/gocodes/datax/schemax/basickind" 8 "gitee.com/zhongguo168a/gocodes/myx/errorx" 9 "strconv" 10 ) 11 12 func NewMapToRef() (obj *MapToRef) { 13 obj = &MapToRef{} 14 return 15 } 16 17 type MapToRef struct { 18 // 19 source map[string]interface{} 20 21 // 忽视空值 22 // 空值不会输出到map中 23 ignoreNil bool 24 } 25 26 func (coder *MapToRef) Reset() { 27 coder.source = nil 28 coder.ignoreNil = false 29 } 30 31 func (coder *MapToRef) SetSource(source map[string]interface{}) *MapToRef { 32 coder.source = source 33 return coder 34 } 35 36 // Create 通过map创建一个对象 37 // map必须设置 key=_type value=string, value指向schemax注册的声明 38 func (coder *MapToRef) Create() (obj reflectx.IRefObject, err error) { 39 _type := mapx.String(coder.source, "_type") 40 if _type == "" { 41 err = errorx.New("_type not found") 42 return 43 } 44 schema := schemax.GetDeclByKey(_type) 45 if schema == nil { 46 err = errorx.New("schema not found: " + _type) 47 return 48 } 49 50 decl, ok := schema.(*schemax.ClassDecl) 51 if !ok { 52 err = errorx.New("decl not schemax.ClassDecl: " + _type) 53 return 54 } 55 56 reftype := reflectx.GetType(_type) 57 if reftype == nil { 58 err = errorx.New("reftype not found: " + decl.RefType()) 59 return 60 } 61 obj = reftype.RefNew() 62 err = coder.fromMapObj(reftype, obj, coder.source, schema, "") 63 if err != nil { 64 err = errorx.Wrap(err, _type) 65 return 66 } 67 return 68 } 69 70 func (coder *MapToRef) Write(obj reflectx.IRefObject) (err error) { 71 schema := schemax.GetDeclByKey(obj.RefType()) 72 if schema == nil { 73 return errorx.New("schema not found: " + obj.RefType()) 74 } 75 reftype := reflectx.GetType(obj.RefType()) 76 if reftype == nil { 77 err = errorx.New("reftype not found: " + obj.RefType()) 78 return 79 } 80 return coder.fromMapObj(reftype, obj, coder.source, schema, "") 81 } 82 83 // keyMode 0-source的字段, 1-所有字段 84 func (coder *MapToRef) fromMapObj(reftype reflectx.IRefType, obj reflectx.IRefObject, smap map[string]interface{}, schema schemax.IDecl, paths string) (err error) { 85 var ( 86 decl = schema.(*schemax.ClassDecl) 87 ) 88 89 allfields := decl.GetAllField() 90 for _, field := range allfields { 91 fname := field.Name 92 alias := field.Alias() 93 94 mval, mhas := smap[alias] 95 if !mhas { 96 continue 97 } 98 fname = alias 99 100 switch ftyp := field.Type.(type) { 101 case *schemax.ClassType: 102 oval, isNil := reftype.(reflectx.IRefField).RefGet(obj, alias) 103 st, classerr := coder.fromMapClass(reftype, oval.(reflectx.IRefObject), isNil, mval, ftyp.Decl, paths+"/"+fname) 104 if classerr != nil { 105 return classerr 106 } 107 reftype.(reflectx.IRefField).RefSet(obj, alias, st) 108 case *schemax.ArrayType: 109 err = coder.fromMapSlice(reftype.(reflectx.IRefSlice), obj, mval, fname, ftyp, paths+"/"+fname) 110 if err != nil { 111 return 112 } 113 case *schemax.MapType: 114 err = coder.fromMapMap(reftype.(reflectx.IRefMap), obj, fname, mval, ftyp, paths+"/"+fname) 115 if err != nil { 116 return 117 } 118 case *schemax.EnumType: 119 st, classerr := coder.fromMapEnum(mval, ftyp.Decl, paths+"/"+fname) 120 if classerr != nil { 121 return classerr 122 } 123 reftype.(reflectx.IRefField).RefSet(obj, field.Name, st) 124 case *schemax.BasicType: 125 reftype.(reflectx.IRefField).RefSet(obj, field.Name, coder.fromMapBasic(mval, ftyp)) 126 case *schemax.AnyType: 127 oval, isNil := reftype.(reflectx.IRefField).RefGet(obj, fname) 128 st, classerr := coder.fromMapAny(reftype, oval, isNil, mval, paths+"/"+fname) 129 if classerr != nil { 130 return classerr 131 } 132 reftype.(reflectx.IRefField).RefSet(obj, fname, st) 133 default: 134 } 135 } 136 return 137 } 138 139 func (coder *MapToRef) fromMapAny(reftype reflectx.IRefType, oany interface{}, isNil bool, sany interface{}, paths string) (st interface{}, err error) { 140 var ( 141 decl string 142 smap map[string]interface{} 143 ismap bool 144 oval reflectx.IRefObject 145 ) 146 if sany == nil { // 返回,并设置obj为nil 147 return 148 } 149 150 if oany == nil { 151 smap, ismap = sany.(map[string]interface{}) 152 if ismap == false { 153 return 154 } 155 decl = mapx.String(smap, "_type") 156 if decl == "" { 157 st = sany 158 return 159 } 160 } else { 161 oval = oany.(reflectx.IRefObject) 162 decl = oval.RefType() 163 } 164 165 st, err = coder.fromMapClass(reftype, oval, isNil, sany.(map[string]interface{}), decl, paths) 166 if err != nil { 167 return 168 } 169 return 170 } 171 172 type TestClass1 struct { 173 } 174 175 func (t *TestClass1) RefType() string { 176 panic("implement me") 177 } 178 179 func (coder *MapToRef) fromMapClass(reftype reflectx.IRefType, oval reflectx.IRefObject, isNil bool, many interface{}, decl string, paths string) (rval reflectx.IRefObject, err error) { 180 if many == nil { // 设置为nil 181 return nil, nil 182 } 183 184 if isNil { 185 rval, err = reflectx.NewObject(decl) 186 if err != nil { 187 err = errorx.New(paths + ": new object " + decl + " : " + err.Error()) 188 return 189 } 190 } else { 191 rval = oval 192 } 193 maptype := reflectx.GetType(decl) 194 if maptype == nil { 195 err = errorx.New(paths + ": reftype not found: " + oval.RefType()) 196 return 197 } 198 199 stdesc := schemax.GetDeclByKey(decl) 200 err = coder.fromMapObj(maptype, rval, many.(map[string]interface{}), stdesc, paths) 201 return 202 } 203 func (coder *MapToRef) fromMapEnum(mval interface{}, decl string, paths string) (st interface{}, err error) { 204 idesc := schemax.GetDeclByKey(decl) 205 if idesc == nil { 206 err = errorx.New(paths + ": enum schema not found: " + decl) 207 return 208 } 209 210 enumdesc := idesc.(*schemax.EnumDecl) 211 st = enumdesc.ConvertToValue(mval) 212 return 213 } 214 215 func (coder *MapToRef) fromMapSlice(reftype reflectx.IRefSlice, obj reflectx.IRefObject, many interface{}, fname string, ftyp *schemax.ArrayType, paths string) (err error) { 216 if many == nil { 217 reftype.RefSet(obj, fname, reftype.RefSliceNew(fname, 0, 0)) 218 return 219 } 220 221 marr := many.([]interface{}) 222 mlen := len(marr) 223 mcap := cap(marr) 224 reftype.RefSet(obj, fname, reftype.RefSliceNew(fname, mlen, mcap)) 225 if mlen == 0 { 226 return 227 } 228 switch etyp := ftyp.Elem.(type) { 229 case *schemax.ClassType: 230 for i := 0; i < len(marr); i++ { 231 mval := marr[i] 232 oval, isNil := reftype.RefSliceGet(obj, fname, i) 233 st, classerr := coder.fromMapClass(reftype, oval.(reflectx.IRefObject), isNil, mval, etyp.Decl, paths+"/"+strconv.Itoa(i)) 234 if classerr != nil { 235 return classerr 236 } 237 reftype.RefSliceSet(obj, fname, i, st) 238 } 239 case *schemax.BasicType: 240 for i := 0; i < len(marr); i++ { 241 reftype.RefSliceSet(obj, fname, i, coder.fromMapBasic(marr[i], etyp)) 242 } 243 case *schemax.EnumType: 244 for i := 0; i < len(marr); i++ { 245 mval := marr[i] 246 rval, classerr := coder.fromMapEnum(mval, etyp.Decl, paths+"/"+strconv.Itoa(i)) 247 if classerr != nil { 248 return classerr 249 } 250 reftype.RefSliceSet(obj, fname, i, rval) 251 } 252 case *schemax.AnyType: 253 254 default: 255 err = errorx.New("decode array: not support type: " + etyp.String()) 256 return 257 258 } 259 260 return 261 } 262 263 func (coder *MapToRef) fromMapMap(reftype reflectx.IRefMap, obj reflectx.IRefObject, fname string, many interface{}, ftyp *schemax.MapType, paths string) (err error) { 264 if many == nil { // 如果设置了nil 265 reftype.RefSet(obj, fname, nil) 266 return 267 } 268 269 mmap := many.(map[string]interface{}) 270 271 _, isNil := reftype.RefGet(obj, fname) 272 if isNil { 273 // 创建 274 reftype.RefSet(obj, fname, reftype.RefMapNew(fname)) 275 } 276 // 277 switch etyp := ftyp.Value.(type) { 278 case *schemax.ClassType: 279 for mkey, mval := range mmap { 280 oval, onil := reftype.RefMapGet(obj, fname, mkey) 281 st, classerr := coder.fromMapClass(reftype, oval.(reflectx.IRefObject), onil, mval, etyp.Decl, paths+"/"+mkey) 282 if classerr != nil { 283 return classerr 284 } 285 reftype.RefMapSet(obj, fname, mkey, st) 286 } 287 case *schemax.BasicType: 288 for mkey, mval := range mmap { 289 reftype.RefMapSet(obj, fname, mkey, coder.fromMapBasic(mval, etyp)) 290 } 291 case *schemax.EnumType: 292 for mkey, mval := range mmap { 293 rval, classerr := coder.fromMapEnum(mval, etyp.Decl, paths+"/"+mkey) 294 if classerr != nil { 295 return classerr 296 } 297 reftype.RefMapSet(obj, fname, mkey, rval) 298 } 299 default: 300 err = errorx.New(paths + ": decode array: not support type: " + etyp.String()) 301 return 302 303 } 304 305 return 306 } 307 308 func (coder *MapToRef) fromMapBasic(mval interface{}, ftyp *schemax.BasicType) interface{} { 309 return basickind.ConvertKindToStruct(ftyp.Kind, mval) 310 }