[GODRIVER-897] ObjectID returned as '000000000000000000000000' Created: 22/Mar/19  Updated: 27/Oct/23  Resolved: 26/Mar/19

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

Type: Bug Priority: Major - P3
Reporter: Ron Dyck Assignee: Isabella Siu (Inactive)
Resolution: Gone away Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

OS X 10.14.3



 Description   

When querying documents with fields storing ObjectIDs, occasionally the ObjectID is returned as: ObjectID("000000000000000000000000"). The actual id in a particular record is: "5c7fd4bbd30c2768159c7119"

The struct looks like:

type Quote struct { 
  ID primitive.ObjectID `bson:"_id" json:"id"`   
  CustomerID primitive.ObjectID `bson:"customerID" json:"customerID"`  
  Discount   *Discount          `bson:"discount" json:"discount,omitempty"`  
  Features   string             `json:"features"`
  JobsheetID primitive.ObjectID `bson:"jobsheetID" json:"jobsheetID"`  
  Number     int                `bson:"number" json:"number"`  
 ...
}

The field that is returned with the 0's is JobsheetID. Oddly the CustomerID is good as is the ID, all of the same ObjectID type. I'm able to successfully query the table referencing the JobsheetID by it's proper _id (ID) and the return results for the ID is good.

Baffled here, I'm attempting to switch from a mgo driver but can't proceed with this issue.



 Comments   
Comment by Ed Pelc [ 09/Apr/20 ]

Thanks for the info! You are always on top of everything.

 

I should be alright probably using `*primitive.ObjectID` in several places. Luckily this really just affects code where the frontend cares if you have an empty id or not(and luckily it's only a few places). The actual go code uses `IsZero()` checks for everything already. Might add something similar to the frontend or a mix not sure yet.

Comment by Divjot Arora (Inactive) [ 09/Apr/20 ]

epelc@greatcloak.com Thank you for confirming. I apologize for the inconvenience here. I believe the root of this issue is that the encoding/json documentation implies that this will work as expected, but it doesn't actually work. In the meantime, you can use *primitive.ObjectID in your structs or marshal to JSON using bson.MarshalExtJSON with the canonical parameter set to false (canonical=false will omit a lot of the extra type information added in canonical extjson).

Comment by Ed Pelc [ 09/Apr/20 ]

Hey Divjot Arora,

You are right, my bad. I forgot a bout that issue and I think I ran into this when I first started using the official driver a while ago. I'll do other workarounds for now. Hope they fix `encoding/json` in the std lib to support Zeroer interface or something.

Comment by Divjot Arora (Inactive) [ 09/Apr/20 ]

Hi epelc@greatcloak.com,

Thank you for the report. I'm not too sure what we could do here to alleviate this. The semantics of the omitempty tag state that the field should be completely omitted from the marshalled JSON if it is considered empty. This is from the json.Marshal docs:

The "omitempty" option specifies that the field should be omitted from the encoding if the field has an empty value, defined as false, 0, a nil pointer, a nil interface value, and any empty array, slice, map, or string.

The issue here is that an array is never considered empty and by the time we get into the ObjectID.MarshalJSON function, the encoding/json library has already decided that the field is non-empty. I consider this a bug in the encoding/json behavior. There is an open ticket in the Go language project for this: https://github.com/golang/go/issues/29310.

Comment by Ed Pelc [ 09/Apr/20 ]

Can this be reopened? I don't think it is fixed as of 1.3.2

Example:

https://play.golang.org/p/LjxfBaCV_1h

Relevant `MarshalJSON` method on `ObjectID` https://github.com/mongodb/mongo-go-driver/blob/master/bson/primitive/objectid.go#L60

 

This really breaks upgrades from mgo and existing code bases which expect object ids to support `omitempty` while marshalling to json in a similar way they do for bson. Expected output is that the `ParentID` key is omitted when the `ObjectId.IsZero()` is true.

 

I have a PR I will submit after lunch to add support for this and handling empty strings when unmarshaling. I did find this other issue which says you can use extended json but this does not support the upgrade path from mgo at all and also changes much of how json marshaling works. Anyways I think my patch will properly support this in an intuitive way by just adding expected omitempty output/input.

Comment by Ian Whalen (Inactive) [ 26/Mar/19 ]

Nope, thanks a lot for letting us know!

Comment by Ron Dyck [ 26/Mar/19 ]

Hi Ian Whalen, this is no longer an issue with v1.0.0. Would you still like a working example?

Please advise.

Comment by Ian Whalen (Inactive) [ 25/Mar/19 ]

hey rond@webbtech.net would it be possible for you to include a fully working example repro?

Comment by Ron Dyck [ 22/Mar/19 ]

Turns out the problem was with the package imported with dep. I was following an earlier tutorial which specified:

dep ensure --add github.com/mongodb/mongo-go-driver/mongo

instead of:
 dep ensure --add go.mongodb.org/mongo-driver/mongo

Comment by Ron Dyck [ 22/Mar/19 ]

Should mention, I installed this lib using dep and see that it's not using the latest version. I'm going to upgrade to 1.0.0.

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