github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/talks/2015/json/unmarshaler1.go (about) 1 // +build OMIT 2 3 package main 4 5 import ( 6 "bytes" 7 "encoding/json" 8 "fmt" 9 "log" 10 "strings" 11 "time" 12 ) 13 14 const input = ` 15 { 16 "name": "Gopher", 17 "birthdate": "2009/11/10", 18 "shirt-size": "XS" 19 } 20 ` 21 22 type Person struct { 23 Name string 24 Born time.Time 25 Size ShirtSize 26 } 27 28 type ShirtSize byte 29 30 const ( 31 NA ShirtSize = iota 32 XS 33 S 34 M 35 L 36 XL 37 ) 38 39 func (ss ShirtSize) String() string { 40 s, ok := map[ShirtSize]string{XS: "XS", S: "S", M: "M", L: "L", XL: "XL"}[ss] 41 if !ok { 42 return "invalid ShirtSize" 43 } 44 return s 45 } 46 47 func ParseShirtSize(s string) (ShirtSize, error) { 48 ss, ok := map[string]ShirtSize{"XS": XS, "S": S, "M": M, "L": L, "XL": XL}[s] 49 if !ok { 50 return NA, fmt.Errorf("invalid ShirtSize %q", s) 51 } 52 return ss, nil 53 } 54 55 func (p *Person) UnmarshalJSON(data []byte) error { 56 var aux struct { 57 Name string 58 Born string `json:"birthdate"` 59 Size string `json:"shirt-size"` 60 } 61 62 dec := json.NewDecoder(bytes.NewReader(data)) // HL 63 if err := dec.Decode(&aux); err != nil { 64 return fmt.Errorf("decode person: %v", err) 65 } 66 p.Name = aux.Name 67 // ... rest of function omitted ... 68 born, err := time.Parse("2006/01/02", aux.Born) 69 if err != nil { 70 return fmt.Errorf("invalid date: %v", err) 71 } 72 p.Born = born 73 p.Size, err = ParseShirtSize(aux.Size) 74 return err 75 } 76 77 func main() { 78 var p Person 79 dec := json.NewDecoder(strings.NewReader(input)) 80 if err := dec.Decode(&p); err != nil { 81 log.Fatalf("parse person: %v", err) 82 } 83 fmt.Println(p) 84 }