// +build ignore,OMIT package main import ( "bytes" "encoding/json" "fmt" "log" "strings" "time" ) const input = `{ "name":"Gopher", "birthdate": "2009/11/10", "shirt-size": "XS" }` type Person struct { Name string Born Date Size ShirtSize } type ShirtSize byte const ( NA ShirtSize = iota XS S M L XL ) func (ss ShirtSize) String() string { s, ok := map[ShirtSize]string{XS: "XS", S: "S", M: "M", L: "L", XL: "XL"}[ss] if !ok { return "invalid ShirtSize" } return s } func (ss *ShirtSize) UnmarshalJSON(data []byte) error { var s string if err := json.Unmarshal(data, &s); err != nil { return fmt.Errorf("shirt-size should be a string, got %s", data) } got, ok := map[string]ShirtSize{"XS": XS, "S": S, "M": M, "L": L, "XL": XL}[s] if !ok { return fmt.Errorf("invalid ShirtSize %q", s) } *ss = got return nil } type Date struct{ time.Time } func (d Date) String() string { return d.Format("2006/01/02") } func (d *Date) UnmarshalJSON(data []byte) error { var s string if err := json.Unmarshal(data, &s); err != nil { return fmt.Errorf("birthdate should be a string, got %s", data) } t, err := time.Parse("2006/01/02", s) // HL if err != nil { return fmt.Errorf("invalid date: %v", err) } d.Time = t return nil } func (p *Person) UnmarshalJSON(data []byte) error { r := bytes.NewReader(data) var aux struct { Name string Born Date `json:"birthdate"` // HL Size ShirtSize `json:"shirt-size"` } if err := json.NewDecoder(r).Decode(&aux); err != nil { return fmt.Errorf("decode person: %v", err) } p.Name = aux.Name p.Size = aux.Size p.Born = aux.Born // HL return nil } func main() { var p Person dec := json.NewDecoder(strings.NewReader(input)) if err := dec.Decode(&p); err != nil { log.Fatalf("parse person: %v", err) } fmt.Println(p) }