github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/talks/2015/json/unmarshaler3.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 "name":"Gopher", 16 "birthdate": "2009/11/10", 17 "shirt-size": "XS" 18 }` 19 20 type Person struct { 21 Name string 22 Born Date 23 Size ShirtSize 24 } 25 26 type ShirtSize byte 27 28 const ( 29 NA ShirtSize = iota 30 XS 31 S 32 M 33 L 34 XL 35 ) 36 37 func (ss ShirtSize) String() string { 38 s, ok := map[ShirtSize]string{XS: "XS", S: "S", M: "M", L: "L", XL: "XL"}[ss] 39 if !ok { 40 return "invalid ShirtSize" 41 } 42 return s 43 } 44 45 func (ss *ShirtSize) UnmarshalJSON(data []byte) error { 46 var s string 47 if err := json.Unmarshal(data, &s); err != nil { 48 return fmt.Errorf("shirt-size should be a string, got %s", data) 49 } 50 got, ok := map[string]ShirtSize{"XS": XS, "S": S, "M": M, "L": L, "XL": XL}[s] 51 if !ok { 52 return fmt.Errorf("invalid ShirtSize %q", s) 53 } 54 *ss = got 55 return nil 56 } 57 58 type Date struct{ time.Time } 59 60 func (d Date) String() string { return d.Format("2006/01/02") } 61 62 func (d *Date) UnmarshalJSON(data []byte) error { 63 var s string 64 if err := json.Unmarshal(data, &s); err != nil { 65 return fmt.Errorf("birthdate should be a string, got %s", data) 66 } 67 t, err := time.Parse("2006/01/02", s) // HL 68 if err != nil { 69 return fmt.Errorf("invalid date: %v", err) 70 } 71 d.Time = t 72 return nil 73 } 74 75 func (p *Person) UnmarshalJSON(data []byte) error { 76 r := bytes.NewReader(data) 77 var aux struct { 78 Name string 79 Born Date `json:"birthdate"` // HL 80 Size ShirtSize `json:"shirt-size"` 81 } 82 if err := json.NewDecoder(r).Decode(&aux); err != nil { 83 return fmt.Errorf("decode person: %v", err) 84 } 85 p.Name = aux.Name 86 p.Size = aux.Size 87 p.Born = aux.Born // HL 88 return nil 89 } 90 91 func main() { 92 var p Person 93 dec := json.NewDecoder(strings.NewReader(input)) 94 if err := dec.Decode(&p); err != nil { 95 log.Fatalf("parse person: %v", err) 96 } 97 fmt.Println(p) 98 }