github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/talks/2015/json/unmarshaler2.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 time.Time 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 // Extract the string from data. 47 var s string 48 if err := json.Unmarshal(data, &s); err != nil { // HL 49 return fmt.Errorf("shirt-size should be a string, got %s", data) 50 } 51 52 // The rest is equivalen to ParseShirtSize. 53 got, ok := map[string]ShirtSize{"XS": XS, "S": S, "M": M, "L": L, "XL": XL}[s] 54 if !ok { 55 return fmt.Errorf("invalid ShirtSize %q", s) 56 } 57 *ss = got // HL 58 return nil 59 } 60 61 func (p *Person) UnmarshalJSON(data []byte) error { 62 var aux struct { 63 Name string 64 Born string `json:"birthdate"` 65 Size ShirtSize `json:"shirt-size"` // HL 66 } 67 68 dec := json.NewDecoder(bytes.NewReader(data)) 69 if err := dec.Decode(&aux); err != nil { 70 return fmt.Errorf("decode person: %v", err) 71 } 72 p.Name = aux.Name 73 p.Size = aux.Size // HL 74 // ... rest of function omitted ... 75 born, err := time.Parse("2006/01/02", aux.Born) 76 if err != nil { 77 return fmt.Errorf("invalid date: %v", err) 78 } 79 p.Born = born 80 return nil 81 } 82 83 func main() { 84 var p Person 85 dec := json.NewDecoder(strings.NewReader(input)) 86 if err := dec.Decode(&p); err != nil { 87 log.Fatalf("parse person: %v", err) 88 } 89 fmt.Println(p) 90 }