| //go:build ignore && OMIT |
| // +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 time.Time |
| 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 { |
| // Extract the string from data. |
| var s string |
| if err := json.Unmarshal(data, &s); err != nil { // HL |
| return fmt.Errorf("shirt-size should be a string, got %s", data) |
| } |
| |
| // The rest is equivalent to ParseShirtSize. |
| 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 // HL |
| return nil |
| } |
| |
| func (p *Person) UnmarshalJSON(data []byte) error { |
| var aux struct { |
| Name string |
| Born string `json:"birthdate"` |
| Size ShirtSize `json:"shirt-size"` // HL |
| } |
| |
| dec := json.NewDecoder(bytes.NewReader(data)) |
| if err := dec.Decode(&aux); err != nil { |
| return fmt.Errorf("decode person: %v", err) |
| } |
| p.Name = aux.Name |
| p.Size = aux.Size // HL |
| // ... rest of function omitted ... |
| born, err := time.Parse("2006/01/02", aux.Born) |
| if err != nil { |
| return fmt.Errorf("invalid date: %v", err) |
| } |
| p.Born = born |
| 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) |
| } |