package acme import ( "encoding" "encoding/json" "errors" "net/mail" "strings" ) var errInvalidContact = errors.New("Ivalid contact") type Contact interface { encoding.TextMarshaler } type Contacts []Contact func (c *Contacts) UnmarshalJSON(b []byte) error { var tmp []string err := json.Unmarshal(b, &tmp) if err != nil { return err } *c = nil // invalidate old value for _, s := range tmp { switch { case strings.HasPrefix(s, "mailto:"): *c = append(*c, Mail(s[7:])) case strings.HasPrefix(s, "tel:"): *c = append(*c, Phone(s[4:])) default: return errInvalidContact } } return nil } type Mail string func (m Mail) MarshalText() ([]byte, error) { return []byte("mailto:" + m), nil } type Phone string func (ph Phone) MarshalText() ([]byte, error) { return []byte("tel:" + ph), nil } func NewMail(email string) (Mail, error) { m, err := mail.ParseAddress(email) if err != nil { return "", err } return Mail(m.Address), nil } func NewPhone(phone string) (Phone, error) { return Phone(phone), nil } func NewContacts(email, phone string) (Contacts, error) { m, err := NewMail(email) if err != nil { return nil, err } c := Contacts{m} if phone != "" { p, _ := NewPhone(phone) c = append(c, p) } return c, nil }