Ho un numero di strutture che richiedono il marshalling personalizzato. Durante i test stavo usando JSON e il normale marshaller JSON. Dato che non esegue il marshalling di campi non esportati, avevo bisogno di scrivere una funzione MarshalJSON personalizzata, che funzionava perfettamente. Quando ho chiamato json.Marshal sulla struttura padre contenente quelli che avevano bisogno del marshalling personalizzato come campi, ha funzionato correttamente.Gestione personalizzata BSON Marshaling (Golang & mgo)
Ora ho bisogno di eseguire il marshalling di tutto su BSON per alcuni lavori di MongoDB e non riesco a trovare alcuna documentazione su come scrivere il marshalling BSON personalizzato. Qualcuno può dirmi come fare l'equivalente per BSON/mgo per quello che ho dimostrato di seguito?
currency.go (le parti più importanti)
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 (ancora una volta, solo le parti rilevanti)
type Product struct {
Name string
Code string
Price currency.Currency
}
Quando chiamo json.Marshal (p) dove p è un prodotto, produce l'output desiderato senza la necessità del modello (non è sicuro del nome) in cui si crea una struttura che è solo un clone con tutti i campi esportati.
A mio parere, l'utilizzo del metodo inline che ho utilizzato semplifica notevolmente l'API e impedisce di disporre di strutture aggiuntive che ingombrano le cose.
Suppongo che il fatto che la struct valuta è dichiarato utilizzando campi non esportati è un refuso? – SirDarius
No, è intenzionale. C'è più codice di ciò che è sopra e io sono un grande sostenitore dell'uso di getter/setter per impedire al programmatore di cambiare semplicemente ciò che vogliono senza riguardo per la logica di business immutabile, più lo strato di astrazione significa qualsiasi cambiamento più avanti sulla linea al funzionamento interno della mia struttura significa che devo cambiare una quantità minima di codice. – leylandski
Inoltre, se si è un utente del pacchetto 'shopspring/decimal', i campi non vengono esportati, quindi in entrambi i casi sarà comunque necessario definire un Getter/Setter personalizzato per abilitare la serializzazione/deserializzazione come mostrato nel risposta. –