package mapstructure import ( "reflect" "strconv" "strings" ) // ComposeDecodeHookFunc creates a single DecodeHookFunc that // automatically composes multiple DecodeHookFuncs. // // The composed funcs are called in order, with the result of the // previous transformation. func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc { return func( f reflect.Kind, t reflect.Kind, data interface{}) (interface{}, error) { var err error for _, f1 := range fs { data, err = f1(f, t, data) if err != nil { return nil, err } // Modify the from kind to be correct with the new data f = getKind(reflect.ValueOf(data)) } return data, nil } } // StringToSliceHookFunc returns a DecodeHookFunc that converts // string to []string by splitting on the given sep. func StringToSliceHookFunc(sep string) DecodeHookFunc { return func( f reflect.Kind, t reflect.Kind, data interface{}) (interface{}, error) { if f != reflect.String || t != reflect.Slice { return data, nil } raw := data.(string) if raw == "" { return []string{}, nil } return strings.Split(raw, sep), nil } } func WeaklyTypedHook( f reflect.Kind, t reflect.Kind, data interface{}) (interface{}, error) { dataVal := reflect.ValueOf(data) switch t { case reflect.String: switch f { case reflect.Bool: if dataVal.Bool() { return "1", nil } else { return "0", nil } case reflect.Float32: return strconv.FormatFloat(dataVal.Float(), 'f', -1, 64), nil case reflect.Int: return strconv.FormatInt(dataVal.Int(), 10), nil case reflect.Slice: dataType := dataVal.Type() elemKind := dataType.Elem().Kind() if elemKind == reflect.Uint8 { return string(dataVal.Interface().([]uint8)), nil } case reflect.Uint: return strconv.FormatUint(dataVal.Uint(), 10), nil } } return data, nil }