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  }