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  }