@@ -231,6 +231,18 @@ type DecoderOptions struct {
231231 // Default string parsing format is time.RFC3339
232232 // Default number parsing format is seconds since January 1, 1970 UTC
233233 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
234246}
235247
236248// 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)
288300 var u Unmarshaler
289301 _ , isNull := av .(* types.AttributeValueMemberNULL )
290302 if av == nil || isNull {
291- u , v = indirect (v , indirectOptions {decodeNull : true })
303+ u , v = indirect [ Unmarshaler ] (v , indirectOptions {decodeNull : true })
292304 if u != nil {
293305 return u .UnmarshalDynamoDBStreamsAttributeValue (av )
294306 }
295307 return d .decodeNull (v )
296308 }
297309
298- u , v = indirect (v , indirectOptions {})
310+ v0 := v
311+ u , v = indirect [Unmarshaler ](v , indirectOptions {})
299312 if u != nil {
300313 return u .UnmarshalDynamoDBStreamsAttributeValue (av )
301314 }
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+ }
302327
303328 switch tv := av .(type ) {
304329 case * types.AttributeValueMemberB :
@@ -420,7 +445,7 @@ func (d *Decoder) decodeBinarySet(bs [][]byte, v reflect.Value) error {
420445 if ! isArray {
421446 v .SetLen (i + 1 )
422447 }
423- u , elem := indirect (v .Index (i ), indirectOptions {})
448+ u , elem := indirect [ Unmarshaler ] (v .Index (i ), indirectOptions {})
424449 if u != nil {
425450 return u .UnmarshalDynamoDBStreamsAttributeValue (& types.AttributeValueMemberBS {Value : bs })
426451 }
@@ -555,7 +580,7 @@ func (d *Decoder) decodeNumberSet(ns []string, v reflect.Value) error {
555580 if ! isArray {
556581 v .SetLen (i + 1 )
557582 }
558- u , elem := indirect (v .Index (i ), indirectOptions {})
583+ u , elem := indirect [ Unmarshaler ] (v .Index (i ), indirectOptions {})
559584 if u != nil {
560585 return u .UnmarshalDynamoDBStreamsAttributeValue (& types.AttributeValueMemberNS {Value : ns })
561586 }
@@ -634,7 +659,7 @@ func (d *Decoder) decodeMap(avMap map[string]types.AttributeValue, v reflect.Val
634659 for k , av := range avMap {
635660 key := reflect .New (keyType ).Elem ()
636661 // handle pointer keys
637- _ , indirectKey := indirect (key , indirectOptions {skipUnmarshaler : true })
662+ _ , indirectKey := indirect [ Unmarshaler ] (key , indirectOptions {skipUnmarshaler : true })
638663 if err := decodeMapKey (k , indirectKey , tag {}); err != nil {
639664 return & UnmarshalTypeError {
640665 Value : fmt .Sprintf ("map key %q" , k ),
@@ -777,7 +802,7 @@ func (d *Decoder) decodeStringSet(ss []string, v reflect.Value) error {
777802 if ! isArray {
778803 v .SetLen (i + 1 )
779804 }
780- u , elem := indirect (v .Index (i ), indirectOptions {})
805+ u , elem := indirect [ Unmarshaler ] (v .Index (i ), indirectOptions {})
781806 if u != nil {
782807 return u .UnmarshalDynamoDBStreamsAttributeValue (& types.AttributeValueMemberSS {Value : ss })
783808 }
@@ -825,7 +850,7 @@ type indirectOptions struct {
825850//
826851// Based on the enoding/json type reflect value type indirection in Go Stdlib
827852// 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 ) {
829854 // Issue #24153 indicates that it is generally not a guaranteed property
830855 // that you may round-trip a reflect.Value by calling Value.Addr().Elem()
831856 // 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
859884 continue
860885 }
861886 if e .Kind () != reflect .Ptr && e .IsValid () {
862- return nil , e
887+ var u U
888+ return u , e
863889 }
864890 }
865891 if v .Kind () != reflect .Ptr {
@@ -880,7 +906,7 @@ func indirect(v reflect.Value, opts indirectOptions) (Unmarshaler, reflect.Value
880906 v .Set (reflect .New (v .Type ().Elem ()))
881907 }
882908 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 {
884910 return u , reflect.Value {}
885911 }
886912 }
@@ -893,7 +919,8 @@ func indirect(v reflect.Value, opts indirectOptions) (Unmarshaler, reflect.Value
893919 }
894920 }
895921
896- return nil , v
922+ var u U
923+ return u , v
897924}
898925
899926// A Number represents a Attributevalue number literal.
0 commit comments