shopspring / decimal

Arbitrary-precision fixed-point decimal numbers in Go
Other
6.35k stars 621 forks source link

Please support UnmarshalBSON and MarshalBSON serialization #168

Open myxtype opened 4 years ago

myxtype commented 4 years ago

Useful when using mongodb databases

myxtype commented 4 years ago
// Unmarshaler is an interface implemented by types that can unmarshal a BSON
// document representation of themselves. The BSON bytes can be assumed to be
// valid. UnmarshalBSON must copy the BSON bytes if it wishes to retain the data
// after returning.
type Unmarshaler interface {
    UnmarshalBSON([]byte) error
}
// Marshaler is an interface implemented by types that can marshal themselves
// into a BSON document represented as bytes. The bytes returned must be a valid
// BSON document if the error is nil.
type Marshaler interface {
    MarshalBSON() ([]byte, error)
}
mwoss commented 4 years ago

Hi @myxtype. Thanks for pointing that. The corresponding PR that already implement the mentioned issue was created some time ago #92, but we haven't decided to merge it to the master branch as it introduces external dependence - we aim for dependency-free lib. We track this issue in our issue board and we will try to comes with a solution in v.1.3 release.

epelc commented 4 years ago

You can work around this by registering a codec for encoding/decoding decimals as strings or some other format(mongodb's decimal128?) without adding a dependency or explicit support to this lib.

https://pkg.go.dev/go.mongodb.org/mongo-driver/bson?tab=doc#MarshalWithRegistry https://pkg.go.dev/go.mongodb.org/mongo-driver@v1.4.0/bson/bsoncodec?tab=doc#Registry

You can even add it to the default registry if it is safe for your project.

NOTE this requires the new official mongodb driver. I don't think mgo or the globalsign fork have any option for registering types/codecs.

mwoss commented 4 years ago

This can might be a valid workaround if we aiming for a dependency-free library. Thanks a lot for the idea @epelc. :D

waghcwb commented 3 years ago

My temporary (and dirty) solution was to create another type extending the default, and update the value when insert in db

type Product struct {
    Price            decimal.Decimal  `bson:"price" json:"price"`
}

type MongoProduct struct {
    Product
    Price string `bson:"price" json:"price"`
}

func CreateProduct(p Product) {
    var product = MongoProduct{}
    product.Price = p.Price.String()
    // insert in db
}