From 266238499b2104c73407c988a6f53baacfc1feed Mon Sep 17 00:00:00 2001 From: kiwigitops <264279439+kiwigitops@users.noreply.github.com> Date: Sat, 20 Jun 2026 17:04:40 -0400 Subject: [PATCH] Fix DynamoDB string accessor type check --- events/attributevalue.go | 14 +++++++------- events/attributevalue_test.go | 11 +++++++++++ 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/events/attributevalue.go b/events/attributevalue.go index 609bce77..85a728e5 100644 --- a/events/attributevalue.go +++ b/events/attributevalue.go @@ -116,13 +116,13 @@ func (av DynamoDBAttributeValue) NumberSet() []string { // String provides access to an attribute of type String. // Method panics if the attribute is not of type String. func (av DynamoDBAttributeValue) String() string { - if av.dataType == DataTypeString { - return av.value.(string) - } - // If dataType is not DataTypeString during fmt.Sprintf("%#v", ...) - // compiler confuses with fmt.Stringer interface and panics - // instead of printing the struct. - return fmt.Sprintf("%v", dynamoDbAttributeValue(av)) + av.ensureType(DataTypeString) + return av.value.(string) +} + +// GoString formats the attribute value without calling the String accessor. +func (av DynamoDBAttributeValue) GoString() string { + return fmt.Sprintf("%#v", dynamoDbAttributeValue(av)) } // StringSet provides access to an attribute of type String Set. diff --git a/events/attributevalue_test.go b/events/attributevalue_test.go index b1b68233..d235ee04 100644 --- a/events/attributevalue_test.go +++ b/events/attributevalue_test.go @@ -5,6 +5,7 @@ package events import ( "encoding/base64" "encoding/json" + "fmt" "testing" "github.com/stretchr/testify/assert" @@ -206,6 +207,7 @@ func TestAccessWithWrongTypePanics(t *testing.T) { {`{ "N": "123.45"}`, func(av DynamoDBAttributeValue) { av.Boolean() }, IncompatibleDynamoDBTypeError{Requested: DataTypeBoolean, Actual: DataTypeNumber}}, {`{ "NS": ["1234", "567.8"] }`, func(av DynamoDBAttributeValue) { av.Boolean() }, IncompatibleDynamoDBTypeError{Requested: DataTypeBoolean, Actual: DataTypeNumberSet}}, {`{ "NULL": true}`, func(av DynamoDBAttributeValue) { av.Number() }, IncompatibleDynamoDBTypeError{Requested: DataTypeNumber, Actual: DataTypeNull}}, + {`{ "BOOL": true}`, func(av DynamoDBAttributeValue) { _ = av.String() }, IncompatibleDynamoDBTypeError{Requested: DataTypeString, Actual: DataTypeBoolean}}, {`{ "S": "Hello"}`, func(av DynamoDBAttributeValue) { av.Number() }, IncompatibleDynamoDBTypeError{Requested: DataTypeNumber, Actual: DataTypeString}}, {`{ "SS": [ "Giraffe", "Zebra" ] }`, func(av DynamoDBAttributeValue) { av.Number() }, IncompatibleDynamoDBTypeError{Requested: DataTypeNumber, Actual: DataTypeStringSet}}, } @@ -219,6 +221,15 @@ func TestAccessWithWrongTypePanics(t *testing.T) { } } +func TestDynamoDBAttributeValueGoStringDoesNotCallStringAccessor(t *testing.T) { + var av DynamoDBAttributeValue + err := json.Unmarshal([]byte(`{ "BOOL": true}`), &av) + assert.Nil(t, err) + formatted := "" + assert.NotPanics(t, func() { formatted = fmt.Sprintf("%#v", av) }) + assert.NotEmpty(t, formatted) +} + func TestMarshalAndUnmarshalString(t *testing.T) { const inputString = "INPUT STRING" inputValue := NewStringAttribute(inputString)