package mapstruct import ( "fmt" "reflect" "strings" "testing" "time" ) type User struct { Name string `json:"name"` Age int `json:"age"` CreatedAt time.Time `json:"created_at"` UpdatedAt *time.Time `json:"updated_at"` Active bool `json:"active"` Score float64 `json:"score"` Address struct { City string `json:"city"` Country string `json:"country"` } `json:"address"` } func TestStruct2Map(t *testing.T) { // 1. Struct to map user := User{ Name: "Alice", Age: 25, CreatedAt: time.Now(), Active: true, Score: 95.5, } user.Address.City = "New York" user.Address.Country = "USA" time2stringHook := func(v reflect.Value, _ reflect.StructField) (any, error) { if v.Type() == reflect.TypeOf(time.Time{}) { if t, ok := v.Interface().(time.Time); ok { return t.Format("2006-01-02 15:04:05"), nil } } return v, nil } result, err := ToMap(user, WithTypeHook(reflect.TypeOf(time.Time{}), time2stringHook)) if err != nil { panic(err) } fmt.Printf("Struct to map:\n%+v\n", result) // 2. Map to struct data := map[string]string{ "name": "Bob", "age": "30", "created_at": "2025-06-04 21:07:10", "active": "true", "score": "88.5", "address.city": "Los Angeles", "address.country": "USA", } var user2 User err = ToStruct(data, &user2) if err != nil { panic(err) } fmt.Printf("\nMap to struct:\n%+v\n", user2) // 3. With custom hooks timeHook := func(s string, _ reflect.StructField) (any, error) { return time.Parse("2006/01/02", s) } nameHook := func(v reflect.Value, _ reflect.StructField) (any, error) { return strings.ToUpper(v.String()), nil } data2 := map[string]string{ "name": "charlie", "created_at": "2025/06/04", } var user3 User err = ToStruct(data2, &user3, WithTagName("json"), WithStringTypeHook(reflect.TypeOf(time.Time{}), timeHook), WithFieldHook("Name", nameHook), ) if err != nil { panic(err) } fmt.Printf("\nWith custom hooks:\n%+v\n", user3) }