duanbishai5271 2015-06-17 12:14
浏览 109
已采纳

处理自定义BSON封送处理

I have a number of structs that require custom marshalling. When I was testing I was using JSON and the standard JSON marshaller. As it doesn't marshal unexported fields, I needed to write a custom MarshalJSON function, which worked perfectly. When I called json.Marshal on the parent struct containing the ones that needed custom marshalling as fields, it worked fine.

Now I need to marshal everything to BSON for some MongoDB work, and I can't find any documentation about how to write custom BSON marshalling. Can anyone tell me how to do the equivalent for BSON/mgo for what I've demonstrated below?

currency.go (the important parts)

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 (again, just the relevant parts)

type Product struct {
    Name  string
    Code  string
    Price currency.Currency
}

When I call json.Marshal(p) where p is a Product, it produces the output I want without the need for the pattern (not sure of the name) where you create a struct which is just a clone with all exported fields.

In my opinion using the inline method I've used greatly simplifies the API and stops you having extra structs that clutter things up.

  • 写回答

1条回答 默认 最新

  • dougou8573 2015-06-17 13:03
    关注

    Custom bson Marshalling/Unmarshalling works nearly the same way, you have to implement the Getter and Setter interfaces respectively

    Something like this should work :

    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
        }
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥30 这是哪个作者做的宝宝起名网站
  • ¥60 版本过低apk如何修改可以兼容新的安卓系统
  • ¥25 由IPR导致的DRIVER_POWER_STATE_FAILURE蓝屏
  • ¥50 有数据,怎么建立模型求影响全要素生产率的因素
  • ¥50 有数据,怎么用matlab求全要素生产率
  • ¥15 TI的insta-spin例程
  • ¥15 完成下列问题完成下列问题
  • ¥15 C#算法问题, 不知道怎么处理这个数据的转换
  • ¥15 YoloV5 第三方库的版本对照问题
  • ¥15 请完成下列相关问题!