处理自定义 BSON 编组
Handling Custom BSON Marshaling
我有许多结构需要自定义编组。当我测试时,我使用的是 JSON 和标准的 JSON 编组器。因为它不编组未导出的字段,所以我需要编写一个自定义的 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 是一个产品,它会产生我想要的输出,而不需要您创建一个结构的模式(不确定名称)克隆所有导出的字段。
在我看来,使用我使用过的内联方法可以大大简化 API 并阻止您使用额外的结构来使事情变得混乱。
自定义 bson Marshalling/Unmarshalling 的工作方式几乎相同,您必须分别实现 Getter and 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
}
}
我有许多结构需要自定义编组。当我测试时,我使用的是 JSON 和标准的 JSON 编组器。因为它不编组未导出的字段,所以我需要编写一个自定义的 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 是一个产品,它会产生我想要的输出,而不需要您创建一个结构的模式(不确定名称)克隆所有导出的字段。
在我看来,使用我使用过的内联方法可以大大简化 API 并阻止您使用额外的结构来使事情变得混乱。
自定义 bson Marshalling/Unmarshalling 的工作方式几乎相同,您必须分别实现 Getter and 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
}
}