github.com/bingoohuang/gg@v0.0.0-20240325092523-45da7dee9335/pkg/mapstruct/examples_test.go (about)

     1  package mapstruct
     2  
     3  import (
     4  	"fmt"
     5  	"time"
     6  )
     7  
     8  func ExampleDecodeTime() { // nolint:govet
     9  	type Person struct {
    10  		Birth time.Time
    11  	}
    12  
    13  	// This input can come from anywhere, but typically comes from
    14  	// something like decoding JSON where we're not quite sure of the
    15  	// struct initially.
    16  	birth := time.Date(2020, 1, 24, 0, 0, 0, 0, time.UTC)
    17  	birthString := birth.Format(time.RFC3339Nano)
    18  
    19  	input := map[string]interface{}{
    20  		"birth": birthString,
    21  	}
    22  
    23  	var result Person
    24  	err := Decode(input, &result)
    25  	if err != nil {
    26  		panic(err)
    27  	}
    28  
    29  	fmt.Println(result.Birth.Format(time.RFC3339Nano))
    30  	// Output:
    31  	// 2020-01-24T00:00:00Z
    32  }
    33  
    34  func ExampleDecode() {
    35  	type Person struct {
    36  		Name   string
    37  		Age    int
    38  		Emails []string
    39  		Extra  map[string]string
    40  	}
    41  
    42  	// This input can come from anywhere, but typically comes from
    43  	// something like decoding JSON where we're not quite sure of the
    44  	// struct initially.
    45  	input := map[string]interface{}{
    46  		"name":   "Mitchell",
    47  		"age":    91,
    48  		"emails": []string{"one", "two", "three"},
    49  		"extra": map[string]string{
    50  			"twitter": "mitchellh",
    51  		},
    52  	}
    53  
    54  	var result Person
    55  	err := Decode(input, &result)
    56  	if err != nil {
    57  		panic(err)
    58  	}
    59  
    60  	fmt.Printf("%#v", result)
    61  	// Output:
    62  	// mapstruct.Person{Name:"Mitchell", Age:91, Emails:[]string{"one", "two", "three"}, Extra:map[string]string{"twitter":"mitchellh"}}
    63  }
    64  
    65  func ExampleDecode_errors() {
    66  	type Person struct {
    67  		Name   string
    68  		Age    int
    69  		Emails []string
    70  		Extra  map[string]string
    71  	}
    72  
    73  	// This input can come from anywhere, but typically comes from
    74  	// something like decoding JSON where we're not quite sure of the
    75  	// struct initially.
    76  	input := map[string]interface{}{
    77  		"name":   123,
    78  		"age":    "bad value",
    79  		"emails": []int{1, 2, 3},
    80  	}
    81  
    82  	var result Person
    83  	err := Decode(input, &result)
    84  	if err == nil {
    85  		panic("should have an error")
    86  	}
    87  
    88  	fmt.Println(err.Error())
    89  	// Output:
    90  	// 5 error(s) decoding:
    91  	//
    92  	// * 'Age' expected type 'int', got unconvertible type 'string', value: 'bad value'
    93  	// * 'Emails[0]' expected type 'string', got unconvertible type 'int', value: '1'
    94  	// * 'Emails[1]' expected type 'string', got unconvertible type 'int', value: '2'
    95  	// * 'Emails[2]' expected type 'string', got unconvertible type 'int', value: '3'
    96  	// * 'Name' expected type 'string', got unconvertible type 'int', value: '123'
    97  }
    98  
    99  func ExampleDecode_metadata() {
   100  	type Person struct {
   101  		Name string
   102  		Age  int
   103  	}
   104  
   105  	// This input can come from anywhere, but typically comes from
   106  	// something like decoding JSON where we're not quite sure of the
   107  	// struct initially.
   108  	input := map[string]interface{}{
   109  		"name":  "Mitchell",
   110  		"age":   91,
   111  		"email": "foo@bar.com",
   112  	}
   113  
   114  	// For metadata, we make a more advanced Config so we can
   115  	// more finely configure the decoder that is used. In this case, we
   116  	// just tell the decoder we want to track metadata.
   117  	var md Metadata
   118  	var result Person
   119  	config := &Config{
   120  		Metadata: &md,
   121  		Result:   &result,
   122  	}
   123  
   124  	decoder, err := NewDecoder(config)
   125  	if err != nil {
   126  		panic(err)
   127  	}
   128  
   129  	if err := decoder.Decode(input); err != nil {
   130  		panic(err)
   131  	}
   132  
   133  	fmt.Printf("Unused keys: %#v", md.Unused)
   134  	// Output:
   135  	// Unused keys: []string{"email"}
   136  }
   137  
   138  func ExampleDecode_weaklyTypedInput() {
   139  	type Person struct {
   140  		Name   string
   141  		Age    int
   142  		Emails []string
   143  	}
   144  
   145  	// This input can come from anywhere, but typically comes from
   146  	// something like decoding JSON, generated by a weakly typed language
   147  	// such as PHP.
   148  	input := map[string]interface{}{
   149  		"name":   123,                      // number => string
   150  		"age":    "42",                     // string => number
   151  		"emails": map[string]interface{}{}, // empty map => empty array
   152  	}
   153  
   154  	var result Person
   155  	config := &Config{
   156  		WeakType: true,
   157  		Result:   &result,
   158  	}
   159  
   160  	decoder, err := NewDecoder(config)
   161  	if err != nil {
   162  		panic(err)
   163  	}
   164  
   165  	err = decoder.Decode(input)
   166  	if err != nil {
   167  		panic(err)
   168  	}
   169  
   170  	fmt.Printf("%#v", result)
   171  	// Output: mapstruct.Person{Name:"123", Age:42, Emails:[]string{}}
   172  }
   173  
   174  func ExampleDecode_tags() {
   175  	// Note that the mapstruct tags defined in the struct type
   176  	// can indicate which fields the values are mapped to.
   177  	type Person struct {
   178  		Name string `mapstruct:"person_name"`
   179  		Age  int    `mapstruct:"person_age"`
   180  	}
   181  
   182  	input := map[string]interface{}{
   183  		"person_name": "Mitchell",
   184  		"person_age":  91,
   185  	}
   186  
   187  	var result Person
   188  	err := Decode(input, &result)
   189  	if err != nil {
   190  		panic(err)
   191  	}
   192  
   193  	fmt.Printf("%#v", result)
   194  	// Output:
   195  	// mapstruct.Person{Name:"Mitchell", Age:91}
   196  }
   197  
   198  func ExampleDecode_embeddedStruct() {
   199  	// Squashing multiple embedded structs is allowed using the squash tag.
   200  	// This is demonstrated by creating a composite struct of multiple types
   201  	// and decoding into it. In this case, a person can carry with it both
   202  	// a Family and a Location, as well as their own FirstName.
   203  	type Family struct {
   204  		LastName string
   205  	}
   206  	type Location struct {
   207  		City string
   208  	}
   209  	type Person struct {
   210  		Family
   211  		Location
   212  		FirstName string
   213  	}
   214  
   215  	input := map[string]interface{}{
   216  		"FirstName": "Mitchell",
   217  		"LastName":  "Hashimoto",
   218  		"City":      "San Francisco",
   219  	}
   220  
   221  	var result Person
   222  	err := Decode(input, &result, WithSquash(true))
   223  	if err != nil {
   224  		panic(err)
   225  	}
   226  
   227  	fmt.Printf("%s %s, %s", result.FirstName, result.LastName, result.City)
   228  	// Output:
   229  	// Mitchell Hashimoto, San Francisco
   230  }
   231  
   232  func ExampleDecode_remainingData() {
   233  	// Note that the mapstruct tags defined in the struct type
   234  	// can indicate which fields the values are mapped to.
   235  	type Person struct {
   236  		Name  string
   237  		Age   int
   238  		Other map[string]interface{} `mapstruct:",remain"`
   239  	}
   240  
   241  	input := map[string]interface{}{
   242  		"name":  "Mitchell",
   243  		"age":   91,
   244  		"email": "mitchell@example.com",
   245  	}
   246  
   247  	var result Person
   248  	err := Decode(input, &result)
   249  	if err != nil {
   250  		panic(err)
   251  	}
   252  
   253  	fmt.Printf("%#v", result)
   254  	// Output:
   255  	// mapstruct.Person{Name:"Mitchell", Age:91, Other:map[string]interface {}{"email":"mitchell@example.com"}}
   256  }
   257  
   258  func ExampleDecode_omitempty() {
   259  	// Add omitempty annotation to avoid map keys for empty values
   260  	type Family struct {
   261  		LastName string
   262  	}
   263  	type Location struct {
   264  		City string
   265  	}
   266  	type Person struct {
   267  		*Family   `mapstruct:",omitempty"`
   268  		*Location `mapstruct:",omitempty"`
   269  		Age       int
   270  		FirstName string
   271  	}
   272  
   273  	result := &map[string]interface{}{}
   274  	input := Person{FirstName: "Somebody"}
   275  	err := Decode(input, &result)
   276  	if err != nil {
   277  		panic(err)
   278  	}
   279  
   280  	fmt.Printf("%+v", result)
   281  	// Output:
   282  	// &map[Age:0 FirstName:Somebody]
   283  }