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

报告相同问题?

悬赏问题

  • ¥15 关于#matlab#的问题:在模糊控制器中选出线路信息,在simulink中根据线路信息生成速度时间目标曲线(初速度为20m/s,15秒后减为0的速度时间图像)我想问线路信息是什么
  • ¥15 banner广告展示设置多少时间不怎么会消耗用户价值
  • ¥16 mybatis的代理对象无法通过@Autowired装填
  • ¥15 可见光定位matlab仿真
  • ¥15 arduino 四自由度机械臂
  • ¥15 wordpress 产品图片 GIF 没法显示
  • ¥15 求三国群英传pl国战时间的修改方法
  • ¥15 matlab代码代写,需写出详细代码,代价私
  • ¥15 ROS系统搭建请教(跨境电商用途)
  • ¥15 AIC3204的示例代码有吗,想用AIC3204测量血氧,找不到相关的代码。