yunion.io/x/jsonutils@v1.0.0/unmarshal.go (about) 1 // Copyright 2019 Yunion 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package jsonutils 16 17 /** 18 jsonutils.Unmarshal 19 20 Fill the value of JSONObject into any object 21 22 */ 23 24 import ( 25 "fmt" 26 "reflect" 27 "strconv" 28 "strings" 29 "time" 30 31 "yunion.io/x/log" 32 "yunion.io/x/pkg/errors" 33 "yunion.io/x/pkg/gotypes" 34 "yunion.io/x/pkg/sortedmap" 35 "yunion.io/x/pkg/tristate" 36 "yunion.io/x/pkg/util/reflectutils" 37 "yunion.io/x/pkg/util/timeutils" 38 "yunion.io/x/pkg/utils" 39 ) 40 41 func (this *JSONValue) Unmarshal(obj interface{}, keys ...string) error { 42 return jsonUnmarshal(this, obj, keys) 43 } 44 45 func (this *JSONArray) Unmarshal(obj interface{}, keys ...string) error { 46 return jsonUnmarshal(this, obj, keys) 47 } 48 49 func (this *JSONDict) Unmarshal(obj interface{}, keys ...string) error { 50 return jsonUnmarshal(this, obj, keys) 51 } 52 53 func jsonUnmarshal(jo JSONObject, o interface{}, keys []string) error { 54 if len(keys) > 0 { 55 var err error = nil 56 jo, err = jo.Get(keys...) 57 if err != nil { 58 return errors.Wrap(err, "Get") 59 } 60 } 61 value := reflect.ValueOf(o) 62 err := jo.unmarshalValue(reflect.Indirect(value)) 63 if err != nil { 64 return errors.Wrap(err, "jo.unmarshalValue") 65 } 66 return nil 67 } 68 69 func (this *JSONValue) unmarshalValue(val reflect.Value) error { 70 if val.CanSet() { 71 zeroVal := reflect.New(val.Type()).Elem() 72 val.Set(zeroVal) 73 } 74 return nil 75 } 76 77 func (this *JSONInt) unmarshalValue(val reflect.Value) error { 78 switch val.Type() { 79 case JSONIntType: 80 json := val.Interface().(JSONInt) 81 json.data = this.data 82 return nil 83 case JSONIntPtrType, JSONObjectType: 84 val.Set(reflect.ValueOf(this)) 85 return nil 86 case JSONStringType: 87 json := val.Interface().(JSONString) 88 json.data = fmt.Sprintf("%d", this.data) 89 return nil 90 case JSONStringPtrType: 91 json := val.Interface().(*JSONString) 92 data := fmt.Sprintf("%d", this.data) 93 if json == nil { 94 json = NewString(data) 95 val.Set(reflect.ValueOf(json)) 96 } else { 97 json.data = data 98 } 99 return nil 100 case JSONBoolType, JSONFloatType, JSONArrayType, JSONDictType, JSONBoolPtrType, JSONFloatPtrType, JSONArrayPtrType, JSONDictPtrType: 101 return ErrTypeMismatch // fmt.Errorf("JSONInt type mismatch %s", val.Type()) 102 case tristate.TriStateType: 103 if this.data == 0 { 104 val.Set(tristate.TriStateFalseValue) 105 } else { 106 val.Set(tristate.TriStateTrueValue) 107 } 108 } 109 switch val.Kind() { 110 case reflect.Int, reflect.Int8, reflect.Int16, 111 reflect.Int32, reflect.Int64: 112 val.SetInt(this.data) 113 case reflect.Uint, reflect.Uint8, reflect.Uint16, 114 reflect.Uint32, reflect.Uint64: 115 val.SetUint(uint64(this.data)) 116 case reflect.Float32, reflect.Float64: 117 val.SetFloat(float64(this.data)) 118 case reflect.Bool: 119 if this.data == 0 { 120 val.SetBool(false) 121 } else { 122 val.SetBool(true) 123 } 124 case reflect.String: 125 val.SetString(fmt.Sprintf("%d", this.data)) 126 case reflect.Ptr: 127 if val.IsNil() { 128 val.Set(reflect.New(val.Type().Elem())) 129 } 130 return this.unmarshalValue(val.Elem()) 131 case reflect.Interface: 132 val.Set(reflect.ValueOf(this.data)) 133 default: 134 return errors.Wrapf(ErrTypeMismatch, "JSONInt vs. %s", val.Type()) 135 } 136 return nil 137 } 138 139 func (this *JSONBool) unmarshalValue(val reflect.Value) error { 140 switch val.Type() { 141 case JSONBoolType: 142 json := val.Interface().(JSONBool) 143 json.data = this.data 144 return nil 145 case JSONBoolPtrType, JSONObjectType: 146 val.Set(reflect.ValueOf(this)) 147 return nil 148 case JSONStringType: 149 json := val.Interface().(JSONString) 150 json.data = strconv.FormatBool(this.data) 151 return nil 152 case JSONStringPtrType: 153 json := val.Interface().(*JSONString) 154 data := strconv.FormatBool(this.data) 155 if json == nil { 156 json = NewString(data) 157 val.Set(reflect.ValueOf(json)) 158 } else { 159 json.data = data 160 } 161 return nil 162 case JSONIntType, JSONFloatType, JSONArrayType, JSONDictType, JSONIntPtrType, JSONFloatPtrType, JSONArrayPtrType, JSONDictPtrType: 163 return ErrTypeMismatch // fmt.Errorf("JSONBool type mismatch %s", val.Type()) 164 case tristate.TriStateType: 165 if this.data { 166 val.Set(tristate.TriStateTrueValue) 167 } else { 168 val.Set(tristate.TriStateFalseValue) 169 } 170 } 171 switch val.Kind() { 172 case reflect.Int, reflect.Uint, reflect.Int8, reflect.Uint8, 173 reflect.Int16, reflect.Uint16, reflect.Int32, reflect.Uint32, reflect.Int64, reflect.Uint64: 174 if this.data { 175 val.SetInt(1) 176 } else { 177 val.SetInt(0) 178 } 179 case reflect.Float32, reflect.Float64: 180 if this.data { 181 val.SetFloat(1.0) 182 } else { 183 val.SetFloat(0.0) 184 } 185 case reflect.Bool: 186 val.SetBool(this.data) 187 case reflect.String: 188 if this.data { 189 val.SetString("true") 190 } else { 191 val.SetString("false") 192 } 193 case reflect.Ptr: 194 if val.IsNil() { 195 val.Set(reflect.New(val.Type().Elem())) 196 } 197 return this.unmarshalValue(val.Elem()) 198 case reflect.Interface: 199 val.Set(reflect.ValueOf(this.data)) 200 default: 201 return errors.Wrapf(ErrTypeMismatch, "JSONBool vs. %s", val.Type()) 202 } 203 return nil 204 } 205 206 func (this *JSONFloat) unmarshalValue(val reflect.Value) error { 207 switch val.Type() { 208 case JSONFloatType: 209 json := val.Interface().(JSONFloat) 210 json.data = this.data 211 return nil 212 case JSONFloatPtrType, JSONObjectType: 213 val.Set(reflect.ValueOf(this)) 214 return nil 215 case JSONStringType: 216 json := val.Interface().(JSONString) 217 json.data = fmt.Sprintf("%f", this.data) 218 return nil 219 case JSONStringPtrType: 220 json := val.Interface().(*JSONString) 221 data := fmt.Sprintf("%f", this.data) 222 if json == nil { 223 json = NewString(data) 224 val.Set(reflect.ValueOf(json)) 225 } else { 226 json.data = data 227 } 228 return nil 229 case JSONIntType: 230 json := val.Interface().(JSONInt) 231 json.data = int64(this.data) 232 return nil 233 case JSONIntPtrType: 234 json := val.Interface().(*JSONInt) 235 if json == nil { 236 json = NewInt(int64(this.data)) 237 val.Set(reflect.ValueOf(json)) 238 } else { 239 json.data = int64(this.data) 240 } 241 return nil 242 case JSONBoolType: 243 json := val.Interface().(JSONBool) 244 json.data = (int(this.data) != 0) 245 return nil 246 case JSONArrayType, JSONDictType, JSONBoolPtrType, JSONArrayPtrType, JSONDictPtrType: 247 return ErrTypeMismatch // fmt.Errorf("JSONFloat type mismatch %s", val.Type()) 248 case tristate.TriStateType: 249 if int(this.data) == 0 { 250 val.Set(tristate.TriStateFalseValue) 251 } else { 252 val.Set(tristate.TriStateTrueValue) 253 } 254 } 255 switch val.Kind() { 256 case reflect.Int, reflect.Uint, reflect.Int8, reflect.Uint8, 257 reflect.Int16, reflect.Uint16, reflect.Int32, reflect.Uint32, reflect.Int64, reflect.Uint64: 258 val.SetInt(int64(this.data)) 259 case reflect.Float32, reflect.Float64: 260 val.SetFloat(this.data) 261 case reflect.Bool: 262 if this.data == 0 { 263 val.SetBool(false) 264 } else { 265 val.SetBool(true) 266 } 267 case reflect.String: 268 val.SetString(fmt.Sprintf("%f", this.data)) 269 case reflect.Ptr: 270 if val.IsNil() { 271 val.Set(reflect.New(val.Type().Elem())) 272 } 273 return this.unmarshalValue(val.Elem()) 274 case reflect.Interface: 275 val.Set(reflect.ValueOf(this.data)) 276 default: 277 return errors.Wrapf(ErrTypeMismatch, "JSONFloat vs. %s", val.Type()) 278 } 279 return nil 280 } 281 282 func (this *JSONString) unmarshalValue(val reflect.Value) error { 283 switch val.Type() { 284 case JSONStringType: 285 json := val.Interface().(JSONString) 286 json.data = this.data 287 return nil 288 case JSONStringPtrType, JSONObjectType: 289 val.Set(reflect.ValueOf(this)) 290 return nil 291 case gotypes.TimeType: 292 var tm time.Time 293 var err error 294 if len(this.data) > 0 { 295 tm, err = timeutils.ParseTimeStr(this.data) 296 if err != nil { 297 log.Warningf("timeutils.ParseTimeStr %s %s", this.data, err) 298 } 299 } else { 300 tm = time.Time{} 301 } 302 val.Set(reflect.ValueOf(tm)) 303 return nil 304 case JSONBoolType: 305 json := val.Interface().(JSONBool) 306 switch strings.ToLower(this.data) { 307 case "true", "yes", "on", "1": 308 json.data = true 309 default: 310 json.data = false 311 } 312 return nil 313 case JSONBoolPtrType: 314 json := val.Interface().(*JSONBool) 315 var data bool 316 switch strings.ToLower(this.data) { 317 case "true", "yes", "on", "1": 318 data = true 319 default: 320 data = false 321 } 322 if json == nil { 323 json = &JSONBool{data: data} 324 } else { 325 json.data = data 326 } 327 return nil 328 case JSONIntType, JSONFloatType, JSONArrayType, JSONDictType, 329 JSONBoolPtrType, JSONIntPtrType, JSONFloatPtrType, JSONArrayPtrType, JSONDictPtrType: 330 return ErrTypeMismatch // fmt.Errorf("JSONString type mismatch %s", val.Type()) 331 case tristate.TriStateType: 332 switch strings.ToLower(this.data) { 333 case "true", "yes", "on", "1": 334 val.Set(tristate.TriStateTrueValue) 335 case "false", "no", "off", "0": 336 val.Set(tristate.TriStateFalseValue) 337 default: 338 val.Set(tristate.TriStateNoneValue) 339 } 340 } 341 switch val.Kind() { 342 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 343 if len(this.data) > 0 { 344 intVal, err := strconv.ParseInt(normalizeCurrencyString(this.data), 10, 64) 345 if err != nil { 346 return err 347 } 348 val.SetInt(intVal) 349 } 350 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 351 if len(this.data) > 0 { 352 intVal, err := strconv.ParseUint(normalizeCurrencyString(this.data), 10, 64) 353 if err != nil { 354 return err 355 } 356 val.SetUint(intVal) 357 } 358 case reflect.Float32, reflect.Float64: 359 if len(this.data) > 0 { 360 floatVal, err := strconv.ParseFloat(normalizeCurrencyString(this.data), 64) 361 if err != nil { 362 return err 363 } 364 val.SetFloat(floatVal) 365 } 366 case reflect.Bool: 367 val.SetBool(utils.ToBool(this.data)) 368 case reflect.String: 369 val.SetString(this.data) 370 case reflect.Ptr: 371 if val.IsNil() { 372 val.Set(reflect.New(val.Type().Elem())) 373 } 374 return this.unmarshalValue(val.Elem()) 375 case reflect.Interface: 376 val.Set(reflect.ValueOf(this.data)) 377 case reflect.Slice: 378 dataLen := 1 379 if val.Cap() < dataLen { 380 newVal := reflect.MakeSlice(val.Type(), dataLen, dataLen) 381 val.Set(newVal) 382 } else if val.Len() != dataLen { 383 val.SetLen(dataLen) 384 } 385 return this.unmarshalValue(val.Index(0)) 386 default: 387 return errors.Wrapf(ErrTypeMismatch, "JSONString vs. %s", val.Type()) 388 } 389 return nil 390 } 391 392 func (this *JSONArray) unmarshalValue(val reflect.Value) error { 393 switch val.Type() { 394 case JSONArrayType: 395 array := val.Interface().(JSONArray) 396 if this.data != nil { 397 array.Add(this.data...) 398 } 399 val.Set(reflect.ValueOf(array)) 400 return nil 401 case JSONArrayPtrType, JSONObjectType: 402 val.Set(reflect.ValueOf(this)) 403 return nil 404 case JSONDictType, JSONIntType, JSONStringType, JSONBoolType, JSONFloatType, 405 JSONDictPtrType, JSONIntPtrType, JSONStringPtrType, JSONBoolPtrType, JSONFloatPtrType: 406 return ErrTypeMismatch //fmt.Errorf("JSONArray type mismatch %s", val.Type()) 407 } 408 switch val.Kind() { 409 case reflect.String: 410 val.SetString(this.String()) 411 return nil 412 case reflect.Ptr: 413 kind := val.Type().Elem().Kind() 414 if kind == reflect.Array || kind == reflect.Slice { 415 if val.IsNil() { 416 val.Set(reflect.New(val.Type().Elem())) 417 } 418 return this.unmarshalValue(val.Elem()) 419 } 420 return ErrTypeMismatch // fmt.Errorf("JSONArray type mismatch %s", val.Type()) 421 case reflect.Interface: 422 val.Set(reflect.ValueOf(this.data)) 423 case reflect.Slice, reflect.Array: 424 if val.Kind() == reflect.Array { 425 if val.Len() != len(this.data) { 426 return ErrArrayLengthMismatch // fmt.Errorf("JSONArray length unmatch %s: %d != %d", val.Type(), val.Len(), len(this.data)) 427 } 428 } else if val.Kind() == reflect.Slice { 429 dataLen := len(this.data) 430 if val.Cap() < dataLen { 431 newVal := reflect.MakeSlice(val.Type(), dataLen, dataLen) 432 val.Set(newVal) 433 } else if val.Len() != dataLen { 434 val.SetLen(dataLen) 435 } 436 } 437 for i, json := range this.data { 438 err := json.unmarshalValue(val.Index(i)) 439 if err != nil { 440 return errors.Wrap(err, "unmarshalValue") 441 } 442 } 443 default: 444 return errors.Wrapf(ErrTypeMismatch, "JSONArray vs. %s", val.Type()) 445 } 446 return nil 447 } 448 449 func (this *JSONDict) unmarshalValue(val reflect.Value) error { 450 switch val.Type() { 451 case JSONDictType: 452 dict := val.Interface().(JSONDict) 453 dict.Update(this) 454 val.Set(reflect.ValueOf(dict)) 455 return nil 456 case JSONDictPtrType, JSONObjectType: 457 val.Set(reflect.ValueOf(this)) 458 return nil 459 case JSONArrayType, JSONIntType, JSONBoolType, JSONFloatType, JSONStringType, 460 JSONArrayPtrType, JSONIntPtrType, JSONBoolPtrType, JSONFloatPtrType, JSONStringPtrType: 461 return ErrTypeMismatch // fmt.Errorf("JSONDict type mismatch %s", val.Type()) 462 } 463 switch val.Kind() { 464 case reflect.String: 465 val.SetString(this.String()) 466 return nil 467 case reflect.Map: 468 return this.unmarshalMap(val) 469 case reflect.Struct: 470 return this.unmarshalStruct(val) 471 case reflect.Interface: 472 if val.Type().Implements(gotypes.ISerializableType) { 473 objPtr, err := gotypes.NewSerializable(val.Type()) 474 if err != nil { 475 return err 476 } 477 if objPtr == nil { 478 val.Set(reflect.ValueOf(this.data)) // ??? 479 return nil 480 } 481 err = this.unmarshalValue(reflect.ValueOf(objPtr)) 482 if err != nil { 483 return errors.Wrap(err, "unmarshalValue") 484 } 485 // 486 // XXX 487 // 488 // cannot unmarshal nested anonymous interface 489 // as nested anonymous interface is treated as a named field 490 // please use jsonutils.Deserialize to descrialize such interface 491 // ... 492 // objPtr = gotypes.Transform(val.Type(), objPtr) 493 // 494 val.Set(reflect.ValueOf(objPtr).Convert(val.Type())) 495 } else { 496 return errors.Wrapf(ErrInterfaceUnsupported, "JSONDict.unmarshalValue: %s", val.Type()) 497 } 498 case reflect.Ptr: 499 kind := val.Type().Elem().Kind() 500 if kind == reflect.Struct || kind == reflect.Map { 501 if val.IsNil() { 502 newVal := reflect.New(val.Type().Elem()) 503 val.Set(newVal) 504 } 505 return this.unmarshalValue(val.Elem()) 506 } 507 fallthrough 508 default: 509 return errors.Wrapf(ErrTypeMismatch, "JSONDict.unmarshalValue: %s", val.Type()) 510 } 511 return nil 512 } 513 514 func (this *JSONDict) unmarshalMap(val reflect.Value) error { 515 if val.IsNil() { 516 mapVal := reflect.MakeMap(val.Type()) 517 val.Set(mapVal) 518 } 519 valType := val.Type() 520 keyType := valType.Key() 521 if keyType.Kind() != reflect.String { 522 return ErrMapKeyMustString // fmt.Errorf("map key must be string") 523 } 524 for iter := sortedmap.NewIterator(this.data); iter.HasMore(); iter.Next() { 525 k, vinf := iter.Get() 526 v := vinf.(JSONObject) 527 keyVal := reflect.ValueOf(k) 528 if keyType != keyVal.Type() { 529 keyVal = keyVal.Convert(keyType) 530 } 531 valVal := reflect.New(valType.Elem()).Elem() 532 533 err := v.unmarshalValue(valVal) 534 if err != nil { 535 return errors.Wrap(err, "JSONDict.unmarshalMap") 536 } 537 val.SetMapIndex(keyVal, valVal) 538 } 539 return nil 540 } 541 542 func setStructFieldAt(key string, v JSONObject, fieldValues reflectutils.SStructFieldValueSet, keyIndexMap map[string][]int, visited map[string]bool) error { 543 if visited == nil { 544 visited = make(map[string]bool) 545 } 546 if _, ok := visited[key]; ok { 547 // reference loop detected 548 return nil 549 } 550 visited[key] = true 551 indexes, ok := keyIndexMap[key] 552 if !ok || len(indexes) == 0 { 553 // try less strict match name 554 indexes = fieldValues.GetStructFieldIndexes2(key, false) 555 if len(indexes) == 0 { 556 // no field match k, ignore 557 return nil 558 } 559 } 560 for _, index := range indexes { 561 err := v.unmarshalValue(fieldValues[index].Value) 562 if err != nil { 563 return errors.Wrap(err, "JSONDict.unmarshalStruct") 564 } 565 depInfo, ok := fieldValues[index].Info.Tags[TAG_DEPRECATED_BY] 566 if ok { 567 err := setStructFieldAt(depInfo, v, fieldValues, keyIndexMap, visited) 568 if err != nil { 569 return errors.Wrap(err, "setStructFieldAt") 570 } 571 } 572 } 573 return nil 574 } 575 576 func (this *JSONDict) unmarshalStruct(val reflect.Value) error { 577 fieldValues := reflectutils.FetchStructFieldValueSetForWrite(val) 578 keyIndexMap := fieldValues.GetStructFieldIndexesMap() 579 errs := make([]error, 0) 580 for iter := sortedmap.NewIterator(this.data); iter.HasMore(); iter.Next() { 581 k, vinf := iter.Get() 582 v := vinf.(JSONObject) 583 err := setStructFieldAt(k, v, fieldValues, keyIndexMap, nil) 584 if err != nil { 585 // store error, not interrupt the process 586 errs = append(errs, errors.Wrapf(err, "setStructFieldAt %s: %s", k, v)) 587 } 588 } 589 callStructAfterUnmarshal(val) 590 if len(errs) > 0 { 591 return errors.NewAggregate(errs) 592 } else { 593 return nil 594 } 595 } 596 597 func callStructAfterUnmarshal(val reflect.Value) { 598 switch val.Kind() { 599 case reflect.Struct: 600 structType := val.Type() 601 for i := 0; i < val.NumField(); i++ { 602 fieldType := structType.Field(i) 603 if fieldType.Anonymous { 604 callStructAfterUnmarshal(val.Field(i)) 605 } 606 } 607 valPtr := val.Addr() 608 afterMarshalFunc := valPtr.MethodByName("AfterUnmarshal") 609 if afterMarshalFunc.IsValid() && !afterMarshalFunc.IsNil() { 610 afterMarshalFunc.Call([]reflect.Value{}) 611 } 612 case reflect.Ptr: 613 callStructAfterUnmarshal(val.Elem()) 614 } 615 }