web-dev-qa-db-ja.com

カスタムBSONマーシャリングの処理

カスタムマーシャリングを必要とする構造体がいくつかあります。テストしていたときは、JSONと標準のJSONマーシャラーを使用していました。エクスポートされていないフィールドをマーシャリングしないため、完全に機能するカスタムMarshalJSON関数を作成する必要がありました。フィールドとしてカスタムマーシャリングが必要なものを含む親構造体でjson.Marshalを呼び出したところ、正常に機能しました。

ここで、MongoDBの作業のためにすべてをBSONにマーシャリングする必要がありますが、カスタム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
}

PがProductであるjson.Marshal(p)を呼び出すと、エクスポートされたすべてのフィールドを持つ単なるクローンである構造体を作成するパターン(名前がわからない)を必要とせずに、必要な出力が生成されます。

私の意見では、私が使用したインラインメソッドを使用すると、APIが大幅に簡素化され、煩雑になる余分な構造体がなくなります。

12
leylandski

カスタム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
    }
}
20
HectorJ