gitee.com/zhongguo168a/gocodes@v0.0.0-20230609140523-e1828349603f/datax/jsonmap/jsonmap-to-struct.go (about) 1 package jsonmap 2 3 import ( 4 "errors" 5 "gitee.com/zhongguo168a/gocodes/datax/schemax/fieldkind" 6 "reflect" 7 "strconv" 8 ) 9 10 var ( 11 refNil = reflect.ValueOf(nil) 12 ) 13 14 func MapToStruct(from map[string]interface{}, to interface{}) (err error) { 15 if from == nil { 16 return 17 } 18 if to == nil { 19 return 20 } 21 err = structFromMapObj(reflect.ValueOf(to), nil, from) 22 if err != nil { 23 return err 24 } 25 26 return 27 } 28 29 func structFromMapObj(sourceRef reflect.Value, sourceTyp reflect.Type, itargetMap interface{}) (err error) { 30 var isTargetNil bool 31 targetMap, ok := itargetMap.(map[string]interface{}) 32 if ok { 33 if targetMap == nil { 34 isTargetNil = true 35 } 36 } else { 37 isTargetNil = true 38 } 39 40 if sourceRef.Kind() == reflect.Ptr { 41 if isTargetNil { 42 sourceRef.Set(refNil) 43 return 44 } 45 if sourceTyp != nil { 46 sourceTyp = sourceTyp.Elem() 47 } 48 if sourceRef.IsNil() { 49 if sourceTyp == nil { 50 return // 无法创建新的对象,返回 51 } 52 sourceRef.Set(reflect.New(sourceTyp)) 53 } 54 sourceRef = sourceRef.Elem() 55 56 } else { 57 if isTargetNil { 58 return 59 } 60 } 61 62 if sourceTyp == nil { 63 sourceTyp = sourceRef.Type() 64 } 65 for i := 0; i < sourceTyp.NumField(); i++ { 66 field := sourceTyp.Field(i) 67 jsonzTagStr := field.Tag.Get("jsonz") 68 if jsonzTagStr == "_" { 69 continue 70 } 71 //tags := parseTag(jsonzTagStr) 72 fname := field.Name 73 lastName := func() (x string) { 74 jsontag := field.Tag.Get("alias") 75 x = jsontag 76 if x == "" { 77 x = fname 78 } 79 return 80 }() 81 valRef := sourceRef.Field(i) 82 ftyp := field.Type 83 catalog := fieldkind.ReflectToFieldKind(ftyp) 84 85 tval, thas := targetMap[lastName] 86 if catalog == fieldkind.Class && field.Anonymous { 87 88 } else { 89 if !thas { // 如果目标map不存在字段,则不作任何动作 90 continue 91 } 92 } 93 94 switch catalog { 95 case fieldkind.Class: 96 if field.Anonymous { 97 err = structFromMapObj(valRef, ftyp, targetMap) 98 if err != nil { 99 err = errors.New(err.Error() + " at class field=" + field.Name) 100 return 101 } 102 } else { 103 err = structFromMapObj(valRef, ftyp, tval) 104 if err != nil { 105 err = errors.New(err.Error() + " at class field=" + field.Name) 106 return 107 } 108 } 109 case fieldkind.Array: 110 err = structFromMapArray(valRef, ftyp, tval) 111 if err != nil { 112 err = errors.New(err.Error() + " at class field=" + field.Name) 113 return 114 } 115 case fieldkind.Map: 116 err = structFromMapMap(valRef, tval, ftyp) 117 if err != nil { 118 err = errors.New(err.Error() + " at class field=" + field.Name) 119 return 120 } 121 case fieldkind.Enum: 122 err = structFromMapEnum(ftyp, valRef, tval) 123 if err != nil { 124 err = errors.New(err.Error() + " at class field=" + field.Name) 125 return 126 } 127 case fieldkind.Basic: 128 err = structFromMapBasic(ftyp, valRef, ConvertJsonKeyToReflectKind(ftyp.Kind(), tval)) 129 if err != nil { 130 err = errors.New(err.Error() + " at class field=" + field.Name) 131 return 132 } 133 case fieldkind.Any: 134 r, anyerr := structFromMapAny(ftyp, valRef, tval) 135 if anyerr != nil { 136 err = errors.New(anyerr.Error() + " at class field=" + field.Name) 137 return 138 } 139 valRef.Set(r) 140 default: 141 err = errors.New("not support: " + ftyp.String()) 142 return 143 144 } 145 } 146 return 147 } 148 149 func structFromMapAny(ftyp reflect.Type, val reflect.Value, target interface{}) (r reflect.Value, err error) { 150 switch tval := target.(type) { 151 case map[string]interface{}: 152 r = reflect.ValueOf(target) 153 default: 154 target = InterfaceToJSONValue(tval) 155 r = reflect.ValueOf(target) 156 } 157 return 158 } 159 160 func structFromMapEnum(ftyp reflect.Type, val reflect.Value, target interface{}) (err error) { 161 tarref := reflect.ValueOf(target) 162 if tarref.Type().String() != ftyp.String() { 163 if !tarref.Type().ConvertibleTo(ftyp) { 164 err = errors.New("cannot convert to " + ftyp.String()) 165 return 166 } 167 168 tarref = tarref.Convert(ftyp) 169 } 170 val.Set(tarref) 171 return 172 } 173 174 func structFromMapBasic(basic reflect.Type, val reflect.Value, target interface{}) (err error) { 175 if !reflect.ValueOf(target).Type().ConvertibleTo(basic) { 176 err = errors.New("cannot convert to " + basic.String()) 177 return 178 } 179 val.Set(reflect.ValueOf(target).Convert(basic)) 180 return 181 } 182 183 func structFromMapArray(sourceArr reflect.Value, ftyp reflect.Type, itarget interface{}) (err error) { 184 var isTargetNil bool 185 targetArr, ok := itarget.([]interface{}) 186 if ok { 187 if targetArr == nil { 188 isTargetNil = true 189 } 190 } else { 191 isTargetNil = true 192 } 193 if isTargetNil { 194 // todo: 将数组设置成nil? 195 //sourceArr.Set(refNil) 196 return 197 } 198 199 elemTyp := ftyp.Elem() 200 201 sourceArr.Set(reflect.MakeSlice(ftyp, len(targetArr), cap(targetArr))) 202 catalog := fieldkind.ReflectToFieldKind(elemTyp) 203 switch catalog { 204 case fieldkind.Class: 205 for i := 0; i < sourceArr.Len(); i++ { 206 classerr := structFromMapObj(sourceArr.Index(i), elemTyp, targetArr[i]) 207 if classerr != nil { 208 err = errors.New("at index=" + strconv.Itoa(i) + ": " + classerr.Error()) 209 return 210 } 211 } 212 case fieldkind.Basic: 213 for i := 0; i < sourceArr.Len(); i++ { 214 err = structFromMapBasic(elemTyp, sourceArr.Index(i), targetArr[i]) 215 if err != nil { 216 err = errors.New("at index=" + strconv.Itoa(i) + ": " + err.Error()) 217 return 218 } 219 220 } 221 case fieldkind.Any: 222 for i := 0; i < sourceArr.Len(); i++ { 223 elemVal := sourceArr.Index(i) 224 r, anyerr := structFromMapAny(ftyp, elemVal, targetArr[i]) 225 if anyerr != nil { 226 err = errors.New("at index=" + strconv.Itoa(i) + ": " + err.Error()) 227 return 228 } 229 elemVal.Set(r) 230 } 231 default: 232 err = errors.New("not support: " + elemTyp.String()) 233 return 234 } 235 return 236 } 237 238 func structFromMapMap(sourceRef reflect.Value, itarget interface{}, ftyp reflect.Type) (err error) { 239 var isTargetNil bool 240 targetMap, ok := itarget.(map[string]interface{}) 241 if ok { 242 if targetMap == nil { 243 isTargetNil = true 244 } 245 } else { 246 isTargetNil = true 247 } 248 if isTargetNil { 249 if !sourceRef.IsNil() { 250 sourceRef.Set(refNil) 251 } 252 return 253 } 254 // 如果 map存在,对象不存在,初始化对象 255 if sourceRef.IsNil() { 256 sourceRef.Set(reflect.MakeMap(ftyp)) 257 } 258 259 keytyp := ftyp.Key() 260 vtyp := ftyp.Elem() 261 for tkey, tval := range targetMap { 262 ckey := reflect.ValueOf(ConvertJsonKeyToReflectKind(ftyp.Key().Kind(), tkey)) 263 ckey = ckey.Convert(keytyp) 264 valRef := sourceRef.MapIndex(ckey) 265 catalog := fieldkind.ReflectToFieldKind(vtyp) 266 switch catalog { 267 case fieldkind.Class: 268 err = structFromMapObj(valRef, vtyp, tval) 269 if err != nil { 270 err = errors.New(err.Error() + "at map key=" + ckey.String()) 271 return 272 } 273 case fieldkind.Enum: 274 err = structFromMapEnum(vtyp, valRef, tval) 275 if err != nil { 276 err = errors.New(err.Error() + "at map key=" + ckey.String()) 277 return 278 } 279 case fieldkind.Basic: 280 sourceRef.SetMapIndex(ckey, reflect.ValueOf(tval).Convert(vtyp)) 281 case fieldkind.Any: 282 r, anyerr := structFromMapAny(ftyp, valRef, tval) 283 if anyerr != nil { 284 err = errors.New(anyerr.Error() + " at map key=" + ckey.String()) 285 return 286 } 287 sourceRef.SetMapIndex(ckey, r) 288 289 default: 290 err = errors.New("not support: " + vtyp.String()) 291 return 292 } 293 } 294 295 return 296 }