I’m using golang mongo driver to get data from mongodb, I have a field that sometimes can be a string, bool… so I need to write a custom type to parse it into int64 when read from database, here is example code:

type Product struct { Id string `json:"id" bson:"_id"` TotalForSell *DBInt64 `json:"total_for_sell" bson:"total_for_sell,omitempty"` } type DBInt64 int64 func (i DBInt64) MarshalBSONValue() (bsontype.Type, []byte, error) { return bson.MarshalValue(int64(i)) } func (i *DBInt64) UnmarshalBSONValue(t bsontype.Type, value []byte) error { switch t { case bson.TypeInt32: intValue, _, ok := bsoncore.ReadInt32(value) if !ok { return fmt.Errorf("failed to read BSON int32") } *i = DBInt64(intValue) case bson.TypeInt64: intValue, _, ok := bsoncore.ReadInt64(value) if !ok { return fmt.Errorf("failed to read BSON int64") } *i = DBInt64(intValue) case bson.TypeString: s, _, ok := bsoncore.ReadString(value) if !ok { return fmt.Errorf("failed to read BSON string") } if utils.IsEmptyString(&s) { *i = DBInt64(0) break } ret, err := strconv.ParseInt(s, 10, 64) if err != nil { return fmt.Errorf("failed to convert BSON string to int64: %s", err.Error()) } *i = DBInt64(ret) case bson.TypeDouble: floatValue, _, ok := bsoncore.ReadDouble(value) if !ok { return fmt.Errorf("failed to read BSON float64") } *i = DBInt64(floatValue) default: *i = DBInt64(0) } return nil } ``` When field ` total_for_sale` was set to `null` in database, I still get 0 in Product struct, my expect is to get `nil` instead, but when I changed type `TotalForSell` to *int64, I can get `nil` as normal, but it cannot parse empty string or bool any more (it will get error if value in database is string or bool, how can I deal with null when I using custom type? I want to get null intead zero values of custom type Here is my specifications: - golang: v1.23 - mongo-driver v1.17.1 Thank you

Sorry, I cant edit the post so I append my issue and expectation here:

When field total_for_sale was set to null in database, I still get 0 in Product struct, my expect is to get nil instead, but when I change type TotalForSell to *int64, I can get nil as normal, but it cannot parse empty string or bool any more (it will get error if value in database is string or bool, how can I deal with null when I using custom type? I want to get null intead zero values of custom type
Here is my specifications:

  • golang: v1.23
  • mongo-driver v1.17.1

Thank you

@Chung_Hoang_Van Your decoder makes the default zero. You need to add a case for bsontype.Null. Optionally, you can deal with this after decoding using the bson.RawValue API:

type Product struct { Id string `json:"id" bson:"_id"` TotalForSellRawValue bson.RawValue `json:"total_for_sell" bson:"total_for_sell,omitempty"` } func (product *Product) TotalForSell() int64 { switch product.TotalForSellRawValue.Type { case bson.TypeInt64: return product.TotalForSellRawValue.Int64() } return 0 }

@Preston_Vasquez
Thank you for your reply, I added a case for type Null like below but still got 0 instead nil
Is there another way to get nil and not use bson.RawValue ?

switch t { case bson.TypeInt32: intValue, _, ok := bsoncore.ReadInt32(value) if !ok { return fmt.Errorf("failed to read BSON int32") } *i = DBInt64(intValue) case bson.TypeInt64: intValue, _, ok := bsoncore.ReadInt64(value) if !ok { return fmt.Errorf("failed to read BSON int64") } *i = DBInt64(intValue) case bson.TypeString: s, _, ok := bsoncore.ReadString(value) if !ok { return fmt.Errorf("failed to read BSON string") } if utils.IsEmptyString(&s) { *i = DBInt64(0) break } ret, err := strconv.ParseInt(s, 10, 64) if err != nil { return fmt.Errorf("failed to convert BSON string to int64: %s", err.Error()) } *i = DBInt64(ret) case bson.TypeDouble: floatValue, _, ok := bsoncore.ReadDouble(value) if !ok { return fmt.Errorf("failed to read BSON float64") } *i = DBInt64(floatValue) case bson.TypeNull: return nil default: *i = DBInt64(0) } return nil }
3 months later

Closed on Feb 8

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.