我有许多需要自定义编组的结构。在测试时,我使用的是JSON和标准的JSON marshaller。由于它不会封送未导出的字段,因此我需要编写一个自定义的MarshalJSON函数,该函数运行良好。当我在父结构上调用json.Marshal时,该结构包含需要自定义编组的字段,它工作正常。
现在,我需要将所有内容封送给BSON进行MongoDB的工作,而我找不到任何有关如何编写自定义BSON封送的文档。谁能告诉我如何用BSON / mgo做类似的事情?
currency.go (重要部分)
type Currency struct { value decimal.Decimal //The actual value of the currency. currencyCode string //The ISO currency code. } /* MarshalJSON implements json.Marshaller. */ func (c Currency) MarshalJSON() ([]byte, error) { f, _ := c.Value().Float64() return json.Marshal(struct { Value float64 `json:"value" bson:"value"` CurrencyCode string `json:"currencyCode" bson:"currencyCode"` }{ Value: f, CurrencyCode: c.CurrencyCode(), }) } /* UnmarshalJSON implements json.Unmarshaller. */ func (c *Currency) UnmarshalJSON(b []byte) error { decoded := new(struct { Value float64 `json:"value" bson:"value"` CurrencyCode string `json:"currencyCode" bson:"currencyCode"` }) jsonErr := json.Unmarshal(b, decoded) if jsonErr == nil { c.value = decimal.NewFromFloat(decoded.Value) c.currencyCode = decoded.CurrencyCode return nil } else { return jsonErr } }
product.go (同样,只是相关部分)
type Product struct { Name string Code string Price currency.Currency }
当我调用json.Marshal(p),其中p是一个Product时,它将生成我想要的输出,而无需使用模式(不确定名称),在该模式中您创建的结构只是一个包含所有导出字段的克隆。
以我的观点,我使用的内联方法大大简化了API,并阻止了您使用多余的结构使事情变得混乱。
自定义bson编组/解组的工作方式几乎相同,您必须分别实现Getter和Setter接口
这样的事情应该工作:
type Currency struct { value decimal.Decimal //The actual value of the currency. currencyCode string //The ISO currency code. } // GetBSON implements bson.Getter. func (c Currency) GetBSON() (interface{}, error) { f := c.Value().Float64() return struct { Value float64 `json:"value" bson:"value"` CurrencyCode string `json:"currencyCode" bson:"currencyCode"` }{ Value: f, CurrencyCode: c.currencyCode, }, nil } // SetBSON implements bson.Setter. func (c *Currency) SetBSON(raw bson.Raw) error { decoded := new(struct { Value float64 `json:"value" bson:"value"` CurrencyCode string `json:"currencyCode" bson:"currencyCode"` }) bsonErr := raw.Unmarshal(decoded) if bsonErr == nil { c.value = decimal.NewFromFloat(decoded.Value) c.currencyCode = decoded.CurrencyCode return nil } else { return bsonErr } }