[GODRIVER-2530] Customer marshal method with pointer receiver not called for map values unless values are pointers Created: 21/Aug/22  Updated: 27/Oct/23  Resolved: 23/Aug/22

Status: Closed
Project: Go Driver
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Bug Priority: Unknown
Reporter: Marc Adkins Assignee: Preston Vasquez
Resolution: Works as Designed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Attachments: File bsonmap.go     Text File output.txt    

 Description   

Summary

Given a container struct with a map and an entity struct with custom Marshaler and Unmarshaler methods. The custom methods are defined using pointer references to the entity struct.

If the map values in the container struct are pointers to the entity struct everything works fine. If the map values are the actual entity structs then the BSONMarshal method isn't called.

Array values seem to work just fine with both pointers and objects.

Please provide the version of the driver. If applicable, please provide the MongoDB server version and topology (standalone, replica set, or sharded cluster).

go.mongodb.org/mongo-driver v1.10.0

$ mongosh
Current Mongosh Log ID:    6302b573833fe31f6ee26647
Connecting to:        mongodb://127.0.0.1:27017/?directConnection=true&serverSelectionTimeoutMS=2000&appName=mongosh+1.5.4
Using MongoDB:        6.0.1
Using Mongosh:        1.5.4

$ go version
go version go1.18.5 linux/amd64

OS: Ubuntu 22.04.1 LTS x86_64

How to Reproduce

See attached program bsonmap.go. Output I'm getting:

Ptr container:
  MarshalBSON()  'listed'->1
  MarshalBSON()  'mapped'->2
  UnmarshalBSON()  text listed|1
  UnmarshalBSON()  text mapped|2
! ptr == ptr2
  ptr1: {['listed'->1] map[ptrKey:'mapped'->2]}
  ptr2: {['listed'->1] map[ptrKey:'mapped'->2]}
Obj container:
  MarshalBSON()  'listed'->1
  UnmarshalBSON()  text listed|1
  UnmarshalBSON()  
Error unmarshaling objContainer: error decoding key index.objKey: wrong number of pieces: 1
* obj1 != obj2
{{  obj1: {[

{listed 1}] map[objKey:\{mapped 2}]}}}
{{  obj2: {[{listed 1}

] map[]}}}

Additional Background

In a more complex scenario (unable to provide this as a simple example at this time) I have seen the following message:

couldn't read length from src, not enough bytes. length=0{}

This is actual where I started trying to nail down the behavior. I suspect there is some relationship. This error only occurs when trying to use objects within maps, but not in arrays, just like in the attached program.



 Comments   
Comment by Marc Adkins [ 22/Aug/22 ]

I filed this same bug against encoding/json and the answer is that "map values are unaddressable" whereas array values are addressable. This is apparently expected behavior.

Confirmed (I guess) with https://go.dev/play/p/RLjONtkgHP8

You should close this bug.

Comment by Marc Adkins [ 22/Aug/22 ]

I have similar code using JSON and YAML. I went back to try and use objects instead of pointers there and neither works. YAML doesn't work at all and JSON seems to have the same behavior as this bug. I'll be digging in there for a bit and will update this bug if I find anything useful.

 

Comment by Marc Adkins [ 21/Aug/22 ]

Something happened to my output text in the body of the issue. I've attached it as an additonal text file output.txt.

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