[GODRIVER-1494] Map keys always use stringer function Created: 21/Feb/20  Updated: 28/Oct/23  Resolved: 13/Apr/20

Status: Closed
Project: Go Driver
Component/s: BSON
Affects Version/s: 1.3.0
Fix Version/s: 1.4.0

Type: Improvement Priority: Major - P3
Reporter: Anonymous User Assignee: Isabella Siu (Inactive)
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Backwards Compatibility: Minor Change

 Description   

When you insert a map into a collection the keys are always `fmt.Sprint`ed, and therefore always use the `String()` function if one exists on that type - this is not always ideal.

 

Please see the below example for a valid use case and further explanation of the current versus desired behaviour:

package mainimport (
"context"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
 
type MyConstantyType stringconst (
	TheFirst  MyConstantyType = "TheFirst"
	TheSecond MyConstantyType = "TheSecond"
)
 
var myConstantyTypeDisplayNames = map[MyConstantyType]string{
	TheFirst:  "The first one",
	TheSecond: "The second one",
}
 
func (m MyConstantyType) String() string {
	return myConstantyTypeDisplayNames[m]
}
 
type OuterType struct {
	Things map[MyConstantyType]int
}
 
func main() {
	opts := options.Client().ApplyURI("mongodb://localhost")
	client, err := mongo.Connect(context.TODO(), opts)
	if err != nil {
		panic(err)
	}
	defer client.Disconnect(context.TODO())	o := &OuterType{
		Things: map[MyConstantyType]int{
			TheFirst:  12312,
			TheSecond: 9876,
		},
	}	/*
		We would expect the above to be stored in the database as:
		{
			"things": {
				"TheFirst": 12312,
				"TheSecond": 9876,
			}
		}		But it is actually stored as:
		{
			"things": {
				"The first one": 12312,
				"The second one": 9876,
			}
		}		This is because of the stringer method `String()` here, which is called from the `fmt.Sprint(key)`
		at https://github.com/mongodb/mongo-go-driver/blob/master/bson/bsoncodec/map_codec.go#L82
	*/	
 
_, err = client.Database("test").Collection("test").InsertOne(context.TODO(), o)	if err != nil {
		panic(err)
	}
}

 

 
 



 Comments   
Comment by Githook User [ 13/Apr/20 ]

Author:

{'name': 'iwysiu', 'email': 'isabella.siu@10gen.com', 'username': 'iwysiu'}

Message: GODRIVER-1494 add option for encoding/json style map encoding (#345)
Branch: master
https://github.com/mongodb/mongo-go-driver/commit/202644fac9d06bcbcd5a1cfcab191ceb2efa899d

Comment by Isabella Siu (Inactive) [ 07/Apr/20 ]

As an update, the map key behavior is being changed to match encoding/json by default, instead of having the mgo behavior by default. While this does change the default behavior, the mgo behavior cannot be roundtripped.

Comment by Isabella Siu (Inactive) [ 25/Feb/20 ]

This is going back into scheduled and will be done before the 1.4 release.

Comment by Isabella Siu (Inactive) [ 25/Feb/20 ]

Hi anonymous.user,

After investigating, we plan to add an option to the MapCodec to have it create keys the same way the encoding/json package does, which will include directly using string types as strings instead of using the Stringer interface. This option will not be turned on by default to avoid changing the default behavior.

After it's done, we'll add an example of how to use this option to this ticket.

Generated at Thu Feb 08 08:36:30 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.