处理自定义BSON Marshaling

ley*_*ski 11 json go mongodb bson

我有许多需要自定义编组的结构.当我测试时,我使用的是JSON和标准的JSON marshaller.因为它没有编组未导出的字段,所以我需要编写一个自定义的MarshalJSON函数,它完美地工作.当我在包含需要自定义编组作为字段的父结构上调用json.Marshal时,它工作正常.

现在我需要为BSO的一些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
    }
}
Run Code Online (Sandbox Code Playgroud)

product.go(再次,只是相关部分)

type Product struct {
    Name  string
    Code  string
    Price currency.Currency
}
Run Code Online (Sandbox Code Playgroud)

当我调用json.Marshal(p),其中p是一个Product时,它产生我想要的输出而不需要模式(不确定名称),在那里创建一个只包含所有导出字段的克隆的结构.

在我看来,使用内联方法,我已经大大简化了API,并阻止你有额外的结构,混乱的东西.

Hec*_*orJ 20

自定义bson编组/解组工作方式几乎相同,必须分别实现GetterSetter接口

这样的事情应该有效:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这正是我想要的!他们没有以与JSON类似的方式命名它,这有点令人讨厌,但你能做些什么. (2认同)
  • 使这个成为一个完美解决方案所需的唯一变化是删除get方法中返回结构周围的bson.Marshal语句,如[this answer]所述(http://stackoverflow.com/questions/30895854/why-wont- MgO的和解组-MY-结构,适当/ 30897080#30897080) (2认同)