@@ -231,6 +231,18 @@ type DecoderOptions struct {
231
231
// Default string parsing format is time.RFC3339
232
232
// Default number parsing format is seconds since January 1, 1970 UTC
233
233
DecodeTime DecodeTimeAttributes
234
+
235
+ // When enabled, the decoder will use implementations of
236
+ // encoding.TextUnmarshaler and encoding.BinaryUnmarshaler when present on
237
+ // unmarshaling targets.
238
+ //
239
+ // If a target implements [Unmarshaler], encoding unmarshaler
240
+ // implementations are ignored.
241
+ //
242
+ // If the attributevalue is a string, its underlying value will be used to
243
+ // call UnmarshalText on the target. If the attributevalue is a binary, its
244
+ // value will be used to call UnmarshalBinary.
245
+ UseEncodingUnmarshalers bool
234
246
}
235
247
236
248
// A Decoder provides unmarshaling AttributeValues to Go value types.
@@ -288,17 +300,30 @@ func (d *Decoder) decode(av types.AttributeValue, v reflect.Value, fieldTag tag)
288
300
var u Unmarshaler
289
301
_ , isNull := av .(* types.AttributeValueMemberNULL )
290
302
if av == nil || isNull {
291
- u , v = indirect (v , indirectOptions {decodeNull : true })
303
+ u , v = indirect [ Unmarshaler ] (v , indirectOptions {decodeNull : true })
292
304
if u != nil {
293
305
return u .UnmarshalDynamoDBStreamsAttributeValue (av )
294
306
}
295
307
return d .decodeNull (v )
296
308
}
297
309
298
- u , v = indirect (v , indirectOptions {})
310
+ v0 := v
311
+ u , v = indirect [Unmarshaler ](v , indirectOptions {})
299
312
if u != nil {
300
313
return u .UnmarshalDynamoDBStreamsAttributeValue (av )
301
314
}
315
+ if d .options .UseEncodingUnmarshalers {
316
+ if s , ok := av .(* types.AttributeValueMemberS ); ok {
317
+ if u , _ := indirect [encoding.TextUnmarshaler ](v0 , indirectOptions {}); u != nil {
318
+ return u .UnmarshalText ([]byte (s .Value ))
319
+ }
320
+ }
321
+ if b , ok := av .(* types.AttributeValueMemberB ); ok {
322
+ if u , _ := indirect [encoding.BinaryUnmarshaler ](v0 , indirectOptions {}); u != nil {
323
+ return u .UnmarshalBinary (b .Value )
324
+ }
325
+ }
326
+ }
302
327
303
328
switch tv := av .(type ) {
304
329
case * types.AttributeValueMemberB :
@@ -420,7 +445,7 @@ func (d *Decoder) decodeBinarySet(bs [][]byte, v reflect.Value) error {
420
445
if ! isArray {
421
446
v .SetLen (i + 1 )
422
447
}
423
- u , elem := indirect (v .Index (i ), indirectOptions {})
448
+ u , elem := indirect [ Unmarshaler ] (v .Index (i ), indirectOptions {})
424
449
if u != nil {
425
450
return u .UnmarshalDynamoDBStreamsAttributeValue (& types.AttributeValueMemberBS {Value : bs })
426
451
}
@@ -555,7 +580,7 @@ func (d *Decoder) decodeNumberSet(ns []string, v reflect.Value) error {
555
580
if ! isArray {
556
581
v .SetLen (i + 1 )
557
582
}
558
- u , elem := indirect (v .Index (i ), indirectOptions {})
583
+ u , elem := indirect [ Unmarshaler ] (v .Index (i ), indirectOptions {})
559
584
if u != nil {
560
585
return u .UnmarshalDynamoDBStreamsAttributeValue (& types.AttributeValueMemberNS {Value : ns })
561
586
}
@@ -634,7 +659,7 @@ func (d *Decoder) decodeMap(avMap map[string]types.AttributeValue, v reflect.Val
634
659
for k , av := range avMap {
635
660
key := reflect .New (keyType ).Elem ()
636
661
// handle pointer keys
637
- _ , indirectKey := indirect (key , indirectOptions {skipUnmarshaler : true })
662
+ _ , indirectKey := indirect [ Unmarshaler ] (key , indirectOptions {skipUnmarshaler : true })
638
663
if err := decodeMapKey (k , indirectKey , tag {}); err != nil {
639
664
return & UnmarshalTypeError {
640
665
Value : fmt .Sprintf ("map key %q" , k ),
@@ -777,7 +802,7 @@ func (d *Decoder) decodeStringSet(ss []string, v reflect.Value) error {
777
802
if ! isArray {
778
803
v .SetLen (i + 1 )
779
804
}
780
- u , elem := indirect (v .Index (i ), indirectOptions {})
805
+ u , elem := indirect [ Unmarshaler ] (v .Index (i ), indirectOptions {})
781
806
if u != nil {
782
807
return u .UnmarshalDynamoDBStreamsAttributeValue (& types.AttributeValueMemberSS {Value : ss })
783
808
}
@@ -825,7 +850,7 @@ type indirectOptions struct {
825
850
//
826
851
// Based on the enoding/json type reflect value type indirection in Go Stdlib
827
852
// https://golang.org/src/encoding/json/decode.go indirect func.
828
- func indirect (v reflect.Value , opts indirectOptions ) (Unmarshaler , reflect.Value ) {
853
+ func indirect [ U any ] (v reflect.Value , opts indirectOptions ) (U , reflect.Value ) {
829
854
// Issue #24153 indicates that it is generally not a guaranteed property
830
855
// that you may round-trip a reflect.Value by calling Value.Addr().Elem()
831
856
// and expect the value to still be settable for values derived from
@@ -859,7 +884,8 @@ func indirect(v reflect.Value, opts indirectOptions) (Unmarshaler, reflect.Value
859
884
continue
860
885
}
861
886
if e .Kind () != reflect .Ptr && e .IsValid () {
862
- return nil , e
887
+ var u U
888
+ return u , e
863
889
}
864
890
}
865
891
if v .Kind () != reflect .Ptr {
@@ -880,7 +906,7 @@ func indirect(v reflect.Value, opts indirectOptions) (Unmarshaler, reflect.Value
880
906
v .Set (reflect .New (v .Type ().Elem ()))
881
907
}
882
908
if ! opts .skipUnmarshaler && v .Type ().NumMethod () > 0 && v .CanInterface () {
883
- if u , ok := v .Interface ().(Unmarshaler ); ok {
909
+ if u , ok := v .Interface ().(U ); ok {
884
910
return u , reflect.Value {}
885
911
}
886
912
}
@@ -893,7 +919,8 @@ func indirect(v reflect.Value, opts indirectOptions) (Unmarshaler, reflect.Value
893
919
}
894
920
}
895
921
896
- return nil , v
922
+ var u U
923
+ return u , v
897
924
}
898
925
899
926
// A Number represents a Attributevalue number literal.
0 commit comments