github.com/aavshr/aws-sdk-go@v1.41.3/service/dynamodb/dynamodbattribute/decode.go (about) 1 package dynamodbattribute 2 3 import ( 4 "encoding/base64" 5 "encoding/json" 6 "fmt" 7 "reflect" 8 "strconv" 9 "time" 10 11 "github.com/aavshr/aws-sdk-go/aws" 12 "github.com/aavshr/aws-sdk-go/service/dynamodb" 13 ) 14 15 // An Unmarshaler is an interface to provide custom unmarshaling of 16 // AttributeValues. Use this to provide custom logic determining 17 // how AttributeValues should be unmarshaled. 18 // type ExampleUnmarshaler struct { 19 // Value int 20 // } 21 // 22 // func (u *ExampleUnmarshaler) UnmarshalDynamoDBAttributeValue(av *dynamodb.AttributeValue) error { 23 // if av.N == nil { 24 // return nil 25 // } 26 // 27 // n, err := strconv.ParseInt(*av.N, 10, 0) 28 // if err != nil { 29 // return err 30 // } 31 // 32 // u.Value = int(n) 33 // return nil 34 // } 35 type Unmarshaler interface { 36 UnmarshalDynamoDBAttributeValue(*dynamodb.AttributeValue) error 37 } 38 39 // Unmarshal will unmarshal DynamoDB AttributeValues to Go value types. 40 // Both generic interface{} and concrete types are valid unmarshal 41 // destination types. 42 // 43 // Unmarshal will allocate maps, slices, and pointers as needed to 44 // unmarshal the AttributeValue into the provided type value. 45 // 46 // When unmarshaling AttributeValues into structs Unmarshal matches 47 // the field names of the struct to the AttributeValue Map keys. 48 // Initially it will look for exact field name matching, but will 49 // fall back to case insensitive if not exact match is found. 50 // 51 // With the exception of omitempty, omitemptyelem, binaryset, numberset 52 // and stringset all struct tags used by Marshal are also used by 53 // Unmarshal. 54 // 55 // When decoding AttributeValues to interfaces Unmarshal will use the 56 // following types. 57 // 58 // []byte, AV Binary (B) 59 // [][]byte, AV Binary Set (BS) 60 // bool, AV Boolean (BOOL) 61 // []interface{}, AV List (L) 62 // map[string]interface{}, AV Map (M) 63 // float64, AV Number (N) 64 // Number, AV Number (N) with UseNumber set 65 // []float64, AV Number Set (NS) 66 // []Number, AV Number Set (NS) with UseNumber set 67 // string, AV String (S) 68 // []string, AV String Set (SS) 69 // 70 // If the Decoder option, UseNumber is set numbers will be unmarshaled 71 // as Number values instead of float64. Use this to maintain the original 72 // string formating of the number as it was represented in the AttributeValue. 73 // In addition provides additional opportunities to parse the number 74 // string based on individual use cases. 75 // 76 // When unmarshaling any error that occurs will halt the unmarshal 77 // and return the error. 78 // 79 // The output value provided must be a non-nil pointer 80 func Unmarshal(av *dynamodb.AttributeValue, out interface{}) error { 81 return NewDecoder().Decode(av, out) 82 } 83 84 // UnmarshalMap is an alias for Unmarshal which unmarshals from 85 // a map of AttributeValues. 86 // 87 // The output value provided must be a non-nil pointer 88 func UnmarshalMap(m map[string]*dynamodb.AttributeValue, out interface{}) error { 89 return NewDecoder().Decode(&dynamodb.AttributeValue{M: m}, out) 90 } 91 92 // UnmarshalList is an alias for Unmarshal func which unmarshals 93 // a slice of AttributeValues. 94 // 95 // The output value provided must be a non-nil pointer 96 func UnmarshalList(l []*dynamodb.AttributeValue, out interface{}) error { 97 return NewDecoder().Decode(&dynamodb.AttributeValue{L: l}, out) 98 } 99 100 // UnmarshalListOfMaps is an alias for Unmarshal func which unmarshals a 101 // slice of maps of attribute values. 102 // 103 // This is useful for when you need to unmarshal the Items from a DynamoDB 104 // Query API call. 105 // 106 // The output value provided must be a non-nil pointer 107 func UnmarshalListOfMaps(l []map[string]*dynamodb.AttributeValue, out interface{}) error { 108 items := make([]*dynamodb.AttributeValue, len(l)) 109 for i, m := range l { 110 items[i] = &dynamodb.AttributeValue{M: m} 111 } 112 113 return UnmarshalList(items, out) 114 } 115 116 // A Decoder provides unmarshaling AttributeValues to Go value types. 117 type Decoder struct { 118 MarshalOptions 119 120 // Instructs the decoder to decode AttributeValue Numbers as 121 // Number type instead of float64 when the destination type 122 // is interface{}. Similar to encoding/json.Number 123 UseNumber bool 124 125 // Instructs the decoder to use Json Number 126 UseJsonNumber bool 127 } 128 129 // NewDecoder creates a new Decoder with default configuration. Use 130 // the `opts` functional options to override the default configuration. 131 func NewDecoder(opts ...func(*Decoder)) *Decoder { 132 d := &Decoder{ 133 MarshalOptions: MarshalOptions{ 134 SupportJSONTags: true, 135 }, 136 } 137 for _, o := range opts { 138 o(d) 139 } 140 141 return d 142 } 143 144 // Decode will unmarshal an AttributeValue into a Go value type. An error 145 // will be return if the decoder is unable to unmarshal the AttributeValue 146 // to the provide Go value type. 147 // 148 // The output value provided must be a non-nil pointer 149 func (d *Decoder) Decode(av *dynamodb.AttributeValue, out interface{}, opts ...func(*Decoder)) error { 150 v := reflect.ValueOf(out) 151 if v.Kind() != reflect.Ptr || v.IsNil() || !v.IsValid() { 152 return &InvalidUnmarshalError{Type: reflect.TypeOf(out)} 153 } 154 155 return d.decode(av, v, tag{}) 156 } 157 158 var stringInterfaceMapType = reflect.TypeOf(map[string]interface{}(nil)) 159 var byteSliceType = reflect.TypeOf([]byte(nil)) 160 var byteSliceSlicetype = reflect.TypeOf([][]byte(nil)) 161 var numberType = reflect.TypeOf(Number("")) 162 var timeType = reflect.TypeOf(time.Time{}) 163 var ptrStringType = reflect.TypeOf(aws.String("")) 164 var jsonNumberType = reflect.TypeOf(json.Number("")) 165 166 func (d *Decoder) decode(av *dynamodb.AttributeValue, v reflect.Value, fieldTag tag) error { 167 var u Unmarshaler 168 if av == nil || av.NULL != nil { 169 u, v = indirect(v, true) 170 if u != nil { 171 return u.UnmarshalDynamoDBAttributeValue(av) 172 } 173 return d.decodeNull(v) 174 } 175 176 u, v = indirect(v, false) 177 if u != nil { 178 return u.UnmarshalDynamoDBAttributeValue(av) 179 } 180 181 switch { 182 case av.B != nil: 183 return d.decodeBinary(av.B, v) 184 case av.BOOL != nil: 185 return d.decodeBool(av.BOOL, v) 186 case av.BS != nil: 187 return d.decodeBinarySet(av.BS, v) 188 case av.L != nil: 189 return d.decodeList(av.L, v) 190 case av.M != nil: 191 return d.decodeMap(av.M, v) 192 case av.N != nil: 193 return d.decodeNumber(av.N, v, fieldTag) 194 case av.NS != nil: 195 return d.decodeNumberSet(av.NS, v) 196 case av.S != nil: 197 return d.decodeString(av.S, v, fieldTag) 198 case av.SS != nil: 199 return d.decodeStringSet(av.SS, v) 200 } 201 202 return nil 203 } 204 205 func (d *Decoder) decodeBinary(b []byte, v reflect.Value) error { 206 if v.Kind() == reflect.Interface { 207 buf := make([]byte, len(b)) 208 copy(buf, b) 209 v.Set(reflect.ValueOf(buf)) 210 return nil 211 } 212 213 if v.Kind() != reflect.Slice && v.Kind() != reflect.Array { 214 return &UnmarshalTypeError{Value: "binary", Type: v.Type()} 215 } 216 217 if v.Type() == byteSliceType { 218 // Optimization for []byte types 219 if v.IsNil() || v.Cap() < len(b) { 220 v.Set(reflect.MakeSlice(byteSliceType, len(b), len(b))) 221 } else if v.Len() != len(b) { 222 v.SetLen(len(b)) 223 } 224 copy(v.Interface().([]byte), b) 225 return nil 226 } 227 228 switch v.Type().Elem().Kind() { 229 case reflect.Uint8: 230 // Fallback to reflection copy for type aliased of []byte type 231 if v.Kind() != reflect.Array && (v.IsNil() || v.Cap() < len(b)) { 232 v.Set(reflect.MakeSlice(v.Type(), len(b), len(b))) 233 } else if v.Len() != len(b) { 234 v.SetLen(len(b)) 235 } 236 for i := 0; i < len(b); i++ { 237 v.Index(i).SetUint(uint64(b[i])) 238 } 239 default: 240 if v.Kind() == reflect.Array { 241 switch v.Type().Elem().Kind() { 242 case reflect.Uint8: 243 reflect.Copy(v, reflect.ValueOf(b)) 244 default: 245 return &UnmarshalTypeError{Value: "binary", Type: v.Type()} 246 } 247 248 break 249 } 250 251 return &UnmarshalTypeError{Value: "binary", Type: v.Type()} 252 } 253 254 return nil 255 } 256 257 func (d *Decoder) decodeBool(b *bool, v reflect.Value) error { 258 switch v.Kind() { 259 case reflect.Bool, reflect.Interface: 260 v.Set(reflect.ValueOf(*b).Convert(v.Type())) 261 default: 262 return &UnmarshalTypeError{Value: "bool", Type: v.Type()} 263 } 264 265 return nil 266 } 267 268 func (d *Decoder) decodeBinarySet(bs [][]byte, v reflect.Value) error { 269 isArray := false 270 271 switch v.Kind() { 272 case reflect.Slice: 273 // Make room for the slice elements if needed 274 if v.IsNil() || v.Cap() < len(bs) { 275 // What about if ignoring nil/empty values? 276 v.Set(reflect.MakeSlice(v.Type(), 0, len(bs))) 277 } 278 case reflect.Array: 279 // Limited to capacity of existing array. 280 isArray = true 281 case reflect.Interface: 282 set := make([][]byte, len(bs)) 283 for i, b := range bs { 284 if err := d.decodeBinary(b, reflect.ValueOf(&set[i]).Elem()); err != nil { 285 return err 286 } 287 } 288 v.Set(reflect.ValueOf(set)) 289 return nil 290 default: 291 return &UnmarshalTypeError{Value: "binary set", Type: v.Type()} 292 } 293 294 for i := 0; i < v.Cap() && i < len(bs); i++ { 295 if !isArray { 296 v.SetLen(i + 1) 297 } 298 u, elem := indirect(v.Index(i), false) 299 if u != nil { 300 return u.UnmarshalDynamoDBAttributeValue(&dynamodb.AttributeValue{BS: bs}) 301 } 302 if err := d.decodeBinary(bs[i], elem); err != nil { 303 return err 304 } 305 } 306 307 return nil 308 } 309 310 func (d *Decoder) decodeNumber(n *string, v reflect.Value, fieldTag tag) error { 311 switch v.Kind() { 312 case reflect.Interface: 313 i, err := d.decodeNumberToInterface(n) 314 if err != nil { 315 return err 316 } 317 v.Set(reflect.ValueOf(i)) 318 return nil 319 case reflect.String: 320 if v.Type() == numberType { // Support Number value type 321 v.Set(reflect.ValueOf(Number(*n))) 322 return nil 323 } 324 v.SetString(*n) 325 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 326 i, err := strconv.ParseInt(*n, 10, 64) 327 if err != nil { 328 return err 329 } 330 if v.OverflowInt(i) { 331 return &UnmarshalTypeError{ 332 Value: fmt.Sprintf("number overflow, %s", *n), 333 Type: v.Type(), 334 } 335 } 336 v.SetInt(i) 337 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 338 i, err := strconv.ParseUint(*n, 10, 64) 339 if err != nil { 340 return err 341 } 342 if v.OverflowUint(i) { 343 return &UnmarshalTypeError{ 344 Value: fmt.Sprintf("number overflow, %s", *n), 345 Type: v.Type(), 346 } 347 } 348 v.SetUint(i) 349 case reflect.Float32, reflect.Float64: 350 i, err := strconv.ParseFloat(*n, 64) 351 if err != nil { 352 return err 353 } 354 if v.OverflowFloat(i) { 355 return &UnmarshalTypeError{ 356 Value: fmt.Sprintf("number overflow, %s", *n), 357 Type: v.Type(), 358 } 359 } 360 v.SetFloat(i) 361 default: 362 if v.Type().ConvertibleTo(timeType) && fieldTag.AsUnixTime { 363 t, err := decodeUnixTime(*n) 364 if err != nil { 365 return err 366 } 367 v.Set(reflect.ValueOf(t).Convert(v.Type())) 368 return nil 369 } 370 return &UnmarshalTypeError{Value: "number", Type: v.Type()} 371 } 372 373 return nil 374 } 375 376 func (d *Decoder) decodeNumberToInterface(n *string) (interface{}, error) { 377 if d.UseJsonNumber { 378 return json.Number(*n), nil 379 } 380 381 if d.UseNumber { 382 return Number(*n), nil 383 } 384 385 // Default to float64 for all numbers 386 return strconv.ParseFloat(*n, 64) 387 } 388 389 func (d *Decoder) decodeNumberSet(ns []*string, v reflect.Value) error { 390 isArray := false 391 392 switch v.Kind() { 393 case reflect.Slice: 394 // Make room for the slice elements if needed 395 if v.IsNil() || v.Cap() < len(ns) { 396 // What about if ignoring nil/empty values? 397 v.Set(reflect.MakeSlice(v.Type(), 0, len(ns))) 398 } 399 case reflect.Array: 400 // Limited to capacity of existing array. 401 isArray = true 402 case reflect.Interface: 403 if d.UseNumber { 404 set := make([]Number, len(ns)) 405 for i, n := range ns { 406 if err := d.decodeNumber(n, reflect.ValueOf(&set[i]).Elem(), tag{}); err != nil { 407 return err 408 } 409 } 410 v.Set(reflect.ValueOf(set)) 411 } else { 412 set := make([]float64, len(ns)) 413 for i, n := range ns { 414 if err := d.decodeNumber(n, reflect.ValueOf(&set[i]).Elem(), tag{}); err != nil { 415 return err 416 } 417 } 418 v.Set(reflect.ValueOf(set)) 419 } 420 return nil 421 default: 422 return &UnmarshalTypeError{Value: "number set", Type: v.Type()} 423 } 424 425 for i := 0; i < v.Cap() && i < len(ns); i++ { 426 if !isArray { 427 v.SetLen(i + 1) 428 } 429 u, elem := indirect(v.Index(i), false) 430 if u != nil { 431 return u.UnmarshalDynamoDBAttributeValue(&dynamodb.AttributeValue{NS: ns}) 432 } 433 if err := d.decodeNumber(ns[i], elem, tag{}); err != nil { 434 return err 435 } 436 } 437 438 return nil 439 } 440 441 func (d *Decoder) decodeList(avList []*dynamodb.AttributeValue, v reflect.Value) error { 442 isArray := false 443 444 switch v.Kind() { 445 case reflect.Slice: 446 // Make room for the slice elements if needed 447 if v.IsNil() || v.Cap() < len(avList) { 448 // What about if ignoring nil/empty values? 449 v.Set(reflect.MakeSlice(v.Type(), 0, len(avList))) 450 } 451 case reflect.Array: 452 // Limited to capacity of existing array. 453 isArray = true 454 case reflect.Interface: 455 s := make([]interface{}, len(avList)) 456 for i, av := range avList { 457 if err := d.decode(av, reflect.ValueOf(&s[i]).Elem(), tag{}); err != nil { 458 return err 459 } 460 } 461 v.Set(reflect.ValueOf(s)) 462 return nil 463 default: 464 return &UnmarshalTypeError{Value: "list", Type: v.Type()} 465 } 466 467 // If v is not a slice, array 468 for i := 0; i < v.Cap() && i < len(avList); i++ { 469 if !isArray { 470 v.SetLen(i + 1) 471 } 472 473 if err := d.decode(avList[i], v.Index(i), tag{}); err != nil { 474 return err 475 } 476 } 477 478 return nil 479 } 480 481 func (d *Decoder) decodeMap(avMap map[string]*dynamodb.AttributeValue, v reflect.Value) error { 482 switch v.Kind() { 483 case reflect.Map: 484 t := v.Type() 485 if t.Key().Kind() != reflect.String { 486 return &UnmarshalTypeError{Value: "map string key", Type: t.Key()} 487 } 488 if v.IsNil() { 489 v.Set(reflect.MakeMap(t)) 490 } 491 case reflect.Struct: 492 case reflect.Interface: 493 v.Set(reflect.MakeMap(stringInterfaceMapType)) 494 v = v.Elem() 495 default: 496 return &UnmarshalTypeError{Value: "map", Type: v.Type()} 497 } 498 499 if v.Kind() == reflect.Map { 500 for k, av := range avMap { 501 key := reflect.New(v.Type().Key()).Elem() 502 key.SetString(k) 503 elem := reflect.New(v.Type().Elem()).Elem() 504 if err := d.decode(av, elem, tag{}); err != nil { 505 return err 506 } 507 v.SetMapIndex(key, elem) 508 } 509 } else if v.Kind() == reflect.Struct { 510 fields := unionStructFields(v.Type(), d.MarshalOptions) 511 for k, av := range avMap { 512 if f, ok := fields.FieldByName(k); ok { 513 fv := decoderFieldByIndex(v, f.Index) 514 if err := d.decode(av, fv, f.tag); err != nil { 515 return err 516 } 517 } 518 } 519 } 520 521 return nil 522 } 523 524 func (d *Decoder) decodeNull(v reflect.Value) error { 525 if v.IsValid() && v.CanSet() { 526 v.Set(reflect.Zero(v.Type())) 527 } 528 529 return nil 530 } 531 532 func (d *Decoder) decodeString(s *string, v reflect.Value, fieldTag tag) error { 533 if fieldTag.AsString { 534 return d.decodeNumber(s, v, fieldTag) 535 } 536 537 // To maintain backwards compatibility with ConvertFrom family of methods which 538 // converted strings to time.Time structs 539 if v.Type().ConvertibleTo(timeType) { 540 t, err := time.Parse(time.RFC3339, *s) 541 if err != nil { 542 return err 543 } 544 v.Set(reflect.ValueOf(t).Convert(v.Type())) 545 return nil 546 } 547 548 switch v.Kind() { 549 case reflect.String: 550 v.SetString(*s) 551 case reflect.Slice: 552 // To maintain backwards compatibility with the ConvertFrom family of methods 553 // which converted []byte into base64-encoded strings if the input was typed 554 if v.Type() == byteSliceType { 555 decoded, err := base64.StdEncoding.DecodeString(*s) 556 if err != nil { 557 return &UnmarshalError{Err: err, Value: "string", Type: v.Type()} 558 } 559 v.SetBytes(decoded) 560 } 561 case reflect.Interface: 562 // Ensure type aliasing is handled properly 563 v.Set(reflect.ValueOf(*s).Convert(v.Type())) 564 default: 565 return &UnmarshalTypeError{Value: "string", Type: v.Type()} 566 } 567 568 return nil 569 } 570 571 func (d *Decoder) decodeStringSet(ss []*string, v reflect.Value) error { 572 isArray := false 573 574 switch v.Kind() { 575 case reflect.Slice: 576 // Make room for the slice elements if needed 577 if v.IsNil() || v.Cap() < len(ss) { 578 v.Set(reflect.MakeSlice(v.Type(), 0, len(ss))) 579 } 580 case reflect.Array: 581 // Limited to capacity of existing array. 582 isArray = true 583 case reflect.Interface: 584 set := make([]string, len(ss)) 585 for i, s := range ss { 586 if err := d.decodeString(s, reflect.ValueOf(&set[i]).Elem(), tag{}); err != nil { 587 return err 588 } 589 } 590 v.Set(reflect.ValueOf(set)) 591 return nil 592 default: 593 return &UnmarshalTypeError{Value: "string set", Type: v.Type()} 594 } 595 596 for i := 0; i < v.Cap() && i < len(ss); i++ { 597 if !isArray { 598 v.SetLen(i + 1) 599 } 600 u, elem := indirect(v.Index(i), false) 601 if u != nil { 602 return u.UnmarshalDynamoDBAttributeValue(&dynamodb.AttributeValue{SS: ss}) 603 } 604 if err := d.decodeString(ss[i], elem, tag{}); err != nil { 605 return err 606 } 607 } 608 609 return nil 610 } 611 612 func decodeUnixTime(n string) (time.Time, error) { 613 v, err := strconv.ParseInt(n, 10, 64) 614 if err != nil { 615 return time.Time{}, &UnmarshalError{ 616 Err: err, Value: n, Type: timeType, 617 } 618 } 619 620 return time.Unix(v, 0), nil 621 } 622 623 // decoderFieldByIndex finds the field with the provided nested index, allocating 624 // embedded parent structs if needed 625 func decoderFieldByIndex(v reflect.Value, index []int) reflect.Value { 626 for i, x := range index { 627 if i > 0 && v.Kind() == reflect.Ptr && v.Type().Elem().Kind() == reflect.Struct { 628 if v.IsNil() { 629 v.Set(reflect.New(v.Type().Elem())) 630 } 631 v = v.Elem() 632 } 633 v = v.Field(x) 634 } 635 return v 636 } 637 638 // indirect will walk a value's interface or pointer value types. Returning 639 // the final value or the value a unmarshaler is defined on. 640 // 641 // Based on the enoding/json type reflect value type indirection in Go Stdlib 642 // https://golang.org/src/encoding/json/decode.go indirect func. 643 func indirect(v reflect.Value, decodingNull bool) (Unmarshaler, reflect.Value) { 644 if v.Kind() != reflect.Ptr && v.Type().Name() != "" && v.CanAddr() { 645 v = v.Addr() 646 } 647 for { 648 if v.Kind() == reflect.Interface && !v.IsNil() { 649 e := v.Elem() 650 if e.Kind() == reflect.Ptr && !e.IsNil() && (!decodingNull || e.Elem().Kind() == reflect.Ptr) { 651 v = e 652 continue 653 } 654 } 655 if v.Kind() != reflect.Ptr { 656 break 657 } 658 if v.Elem().Kind() != reflect.Ptr && decodingNull && v.CanSet() { 659 break 660 } 661 if v.IsNil() { 662 v.Set(reflect.New(v.Type().Elem())) 663 } 664 if v.Type().NumMethod() > 0 { 665 if u, ok := v.Interface().(Unmarshaler); ok { 666 return u, reflect.Value{} 667 } 668 } 669 v = v.Elem() 670 } 671 672 return nil, v 673 } 674 675 // A Number represents a Attributevalue number literal. 676 type Number string 677 678 // Float64 attempts to cast the number ot a float64, returning 679 // the result of the case or error if the case failed. 680 func (n Number) Float64() (float64, error) { 681 return strconv.ParseFloat(string(n), 64) 682 } 683 684 // Int64 attempts to cast the number ot a int64, returning 685 // the result of the case or error if the case failed. 686 func (n Number) Int64() (int64, error) { 687 return strconv.ParseInt(string(n), 10, 64) 688 } 689 690 // Uint64 attempts to cast the number ot a uint64, returning 691 // the result of the case or error if the case failed. 692 func (n Number) Uint64() (uint64, error) { 693 return strconv.ParseUint(string(n), 10, 64) 694 } 695 696 // String returns the raw number represented as a string 697 func (n Number) String() string { 698 return string(n) 699 } 700 701 type emptyOrigError struct{} 702 703 func (e emptyOrigError) OrigErr() error { 704 return nil 705 } 706 707 // An UnmarshalTypeError is an error type representing a error 708 // unmarshaling the AttributeValue's element to a Go value type. 709 // Includes details about the AttributeValue type and Go value type. 710 type UnmarshalTypeError struct { 711 emptyOrigError 712 Value string 713 Type reflect.Type 714 } 715 716 // Error returns the string representation of the error. 717 // satisfying the error interface 718 func (e *UnmarshalTypeError) Error() string { 719 return fmt.Sprintf("%s: %s", e.Code(), e.Message()) 720 } 721 722 // Code returns the code of the error, satisfying the awserr.Error 723 // interface. 724 func (e *UnmarshalTypeError) Code() string { 725 return "UnmarshalTypeError" 726 } 727 728 // Message returns the detailed message of the error, satisfying 729 // the awserr.Error interface. 730 func (e *UnmarshalTypeError) Message() string { 731 return "cannot unmarshal " + e.Value + " into Go value of type " + e.Type.String() 732 } 733 734 // An InvalidUnmarshalError is an error type representing an invalid type 735 // encountered while unmarshaling a AttributeValue to a Go value type. 736 type InvalidUnmarshalError struct { 737 emptyOrigError 738 Type reflect.Type 739 } 740 741 // Error returns the string representation of the error. 742 // satisfying the error interface 743 func (e *InvalidUnmarshalError) Error() string { 744 return fmt.Sprintf("%s: %s", e.Code(), e.Message()) 745 } 746 747 // Code returns the code of the error, satisfying the awserr.Error 748 // interface. 749 func (e *InvalidUnmarshalError) Code() string { 750 return "InvalidUnmarshalError" 751 } 752 753 // Message returns the detailed message of the error, satisfying 754 // the awserr.Error interface. 755 func (e *InvalidUnmarshalError) Message() string { 756 if e.Type == nil { 757 return "cannot unmarshal to nil value" 758 } 759 if e.Type.Kind() != reflect.Ptr { 760 return "cannot unmarshal to non-pointer value, got " + e.Type.String() 761 } 762 return "cannot unmarshal to nil value, " + e.Type.String() 763 } 764 765 // An UnmarshalError wraps an error that occurred while unmarshaling a DynamoDB 766 // AttributeValue element into a Go type. This is different from UnmarshalTypeError 767 // in that it wraps the underlying error that occurred. 768 type UnmarshalError struct { 769 Err error 770 Value string 771 Type reflect.Type 772 } 773 774 // Error returns the string representation of the error. 775 // satisfying the error interface. 776 func (e *UnmarshalError) Error() string { 777 return fmt.Sprintf("%s: %s\ncaused by: %v", e.Code(), e.Message(), e.Err) 778 } 779 780 // OrigErr returns the original error that caused this issue. 781 func (e UnmarshalError) OrigErr() error { 782 return e.Err 783 } 784 785 // Code returns the code of the error, satisfying the awserr.Error 786 // interface. 787 func (e *UnmarshalError) Code() string { 788 return "UnmarshalError" 789 } 790 791 // Message returns the detailed message of the error, satisfying 792 // the awserr.Error interface. 793 func (e *UnmarshalError) Message() string { 794 return fmt.Sprintf("cannot unmarshal %q into %s.", 795 e.Value, e.Type.String()) 796 }