package httpio import ( "encoding/json" "errors" "net/http" "strconv" ) type URLQueryValueType interface { string | int | float32 | float64 | bool } type iURLQueryKeyType interface { GetKey() string } type URLQueryKeyType[T URLQueryValueType] struct { Key string _ T } func (u URLQueryKeyType[T]) GetKey() string { return u.Key } func URLQueryKey[T URLQueryValueType](key string) iURLQueryKeyType { return URLQueryKeyType[T]{ Key: key, } } func ParseURLQuery[T IRequestIO](r *http.Request, keys ...iURLQueryKeyType) (*T, error) { query := make(map[string]any, len(keys)) for _, key := range keys { queryValue := r.URL.Query().Get(key.GetKey()) if queryValue == "" { continue } switch key.(type) { case URLQueryKeyType[string]: query[key.GetKey()] = queryValue case URLQueryKeyType[int]: x, err := strconv.Atoi(queryValue) if err != nil { return nil, err } query[key.GetKey()] = x case URLQueryKeyType[float32]: x, err := strconv.ParseFloat(queryValue, 32) if err != nil { return nil, err } query[key.GetKey()] = x case URLQueryKeyType[float64]: x, err := strconv.ParseFloat(queryValue, 64) if err != nil { return nil, err } query[key.GetKey()] = x case URLQueryKeyType[bool]: x, err := strconv.ParseBool(queryValue) if err != nil { return nil, err } query[key.GetKey()] = x default: return nil, errors.New("unsupported URL query key type") } } queryBytes, _ := json.Marshal(query) var req T err := json.Unmarshal(queryBytes, &req) if err != nil { return nil, err } return &req, nil }