Skip to content

Instantly share code, notes, and snippets.

@17twenty
Created May 7, 2020 07:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 17twenty/5d535d02b2c1f59934c5b332d9251d61 to your computer and use it in GitHub Desktop.
Save 17twenty/5d535d02b2c1f59934c5b332d9251d61 to your computer and use it in GitHub Desktop.
Custom marshal/unmarshal leveraging Scan/Value() for JSON and Database usage
package main
import (
"database/sql/driver"
"encoding/json"
"fmt"
"strings"
)
type paymentOption int64
const (
// PaymentOptionUnknown is an invalid type
PaymentOptionUnknown paymentOption = iota
// PaymentOptionCard means a card payment was made
PaymentOptionCard
// PaymentOptionInstalments means an instalment plan was used
PaymentOptionInstalments
)
// Begin cancer
func (x paymentOption) String() string {
return map[paymentOption]string{
PaymentOptionUnknown: "PaymentOptionUnknown",
PaymentOptionCard: "PaymentOptionCard",
PaymentOptionInstalments: "PaymentOptionInstalments",
}[x]
}
// Scan ...
func (x *paymentOption) Scan(value interface{}) error {
db := value.([]uint8)
// An attempt to fetch a map value with a key that is not present in
// the map will return the zero value for the type of the entries in the map i.e.
// the unknown option
*x = map[string]paymentOption{
"PaymentOptionUnknown": PaymentOptionUnknown,
"PaymentOptionCard": PaymentOptionCard,
"PaymentOptionInstalments": PaymentOptionInstalments,
}[string(db)]
return nil
}
// Value ...
func (x paymentOption) Value() (driver.Value, error) {
return x.String(), nil
}
// MarshalJSON Converts to Byte array
func (x paymentOption) MarshalJSON() ([]byte, error) {
return json.Marshal(strings.ToLower(strings.ReplaceAll(x.String(), "PaymentOption", "")))
}
// UnmarshalJSON Converts from byte array
func (x *paymentOption) UnmarshalJSON(b []byte) error {
var j string
if err := json.Unmarshal(b, &j); err != nil {
return err
}
// Cancer hacks
return x.Scan([]uint8((fmt.Sprintf("PaymentOption%s", strings.Title(j)))))
}
// end cancer
type Test struct {
Bar []paymentOption `json:"bar"`
}
func main() {
data := []byte(`{"bar": ["instalments","card"]}`)
var test Test
var err error
json.Unmarshal(data, &test)
fmt.Printf("After unmarshal: %#v %s\n", test, test)
test.Bar = []paymentOption{PaymentOptionInstalments}
data, err = json.Marshal(test)
fmt.Println(">",err)
fmt.Printf("After marshal: %#v %s\n", string(data), data)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment