Repository: fxamacker/cbor
Pull request #670 (2025-06-08 18:19:55)

Improve DupMapKeyError message
Currently, `DupMapKeyError` uses hard-coded quotes in the error message for map keys, including non-string types.

Given this, an error message containing a quoted integer having a value of 1 looks the same as the string "1" because they both have quotes in the error message.

This PR removes the hard-coded quotes in the error message and replaces `%v` with `%#v` to only emit quotes when applicable.

NOTE: This change is only relevant for user apps that use the non-default `DupMapKeyEnforcedAPF` decoding option.


Patch:
diff --git a/decode.go b/decode.go
index b30087f..514ae5e 100644
--- a/decode.go
+++ b/decode.go
@@ -202,7 +202,7 @@ type DupMapKeyError struct {
 }
 
 func (e *DupMapKeyError) Error() string {
-	return fmt.Sprintf("cbor: found duplicate map key \"%v\" at map element index %d", e.Key, e.Index)
+	return fmt.Sprintf("cbor: found duplicate map key %#v at map element index %d", e.Key, e.Index)
 }
 
 // UnknownFieldError describes detected unknown field in CBOR map when decoding to Go struct.


Test patch:
diff --git a/decode_test.go b/decode_test.go
index 5880d73..aa21dc2 100644
--- a/decode_test.go
+++ b/decode_test.go
@@ -5677,7 +5677,7 @@ func TestUnmarshalDupMapKeyToStructKeyAsInt(t *testing.T) {
 
 	// Duplicate key triggers error.
 	wantS = s{A: 2, B: 4}
-	wantErrorMsg := "cbor: found duplicate map key \"1\" at map element index 2"
+	wantErrorMsg := "cbor: found duplicate map key 1 at map element index 2"
 	dm, _ := DecOptions{DupMapKey: DupMapKeyEnforcedAPF}.DecMode()
 	var s2 s
 	if err := dm.Unmarshal(data, &s2); err == nil {
@@ -5724,7 +5724,7 @@ func TestStreamDupMapKeyToStructKeyAsInt(t *testing.T) {
 
 	// Duplicate key triggers error.
 	wantS = s{A: 2, B: 4}
-	wantErrorMsg := "cbor: found duplicate map key \"1\" at map element index 2"
+	wantErrorMsg := "cbor: found duplicate map key 1 at map element index 2"
 	dm, _ := DecOptions{DupMapKey: DupMapKeyEnforcedAPF}.DecMode()
 	dec = dm.NewDecoder(bytes.NewReader(b))
 	for i := 0; i < 3; i++ {
@@ -5852,7 +5852,7 @@ func TestUnmarshalDupMapKeyToStructKeyAsIntNoMatchingField(t *testing.T) {
 
 	// Duplicate key triggers error even though map key "a" doesn't have a corresponding struct field.
 	wantS = s{B: 4}
-	wantErrorMsg := "cbor: found duplicate map key \"1\" at map element index 2"
+	wantErrorMsg := "cbor: found duplicate map key 1 at map element index 2"
 	dm, _ := DecOptions{DupMapKey: DupMapKeyEnforcedAPF}.DecMode()
 	var s2 s
 	if err := dm.Unmarshal(data, &s2); err == nil {
@@ -5898,7 +5898,7 @@ func TestStreamDupMapKeyToStructKeyAsIntNoMatchingField(t *testing.T) {
 
 	// Duplicate key triggers error.
 	wantS = s{B: 4}
-	wantErrorMsg := "cbor: found duplicate map key \"1\" at map element index 2"
+	wantErrorMsg := "cbor: found duplicate map key 1 at map element index 2"
 	dm, _ := DecOptions{DupMapKey: DupMapKeyEnforcedAPF}.DecMode()
 	dec = dm.NewDecoder(bytes.NewReader(b))
 	for i := 0; i < 3; i++ {
@@ -5944,7 +5944,7 @@ func TestUnmarshalDupMapKeyToStructWrongType(t *testing.T) {
 	}
 
 	wantS = s{A: "A", B: "B", C: "C"}
-	wantErrorMsg = "cbor: found duplicate map key \"100000\" at map element index 4"
+	wantErrorMsg = "cbor: found duplicate map key 100000 at map element index 4"
 	dm, _ := DecOptions{DupMapKey: DupMapKeyEnforcedAPF}.DecMode()
 	var s2 s
 	if err := dm.Unmarshal(data, &s2); err == nil {
@@ -5997,7 +5997,7 @@ func TestStreamDupMapKeyToStructWrongType(t *testing.T) {
 
 	// Duplicate key triggers error.
 	wantS = s{A: "A", B: "B", C: "C"}
-	wantErrorMsg = "cbor: found duplicate map key \"100000\" at map element index 4"
+	wantErrorMsg = "cbor: found duplicate map key 100000 at map element index 4"
 	dm, _ := DecOptions{DupMapKey: DupMapKeyEnforcedAPF}.DecMode()
 	dec = dm.NewDecoder(bytes.NewReader(b))
 	for i := 0; i < 3; i++ {