package router import ( "fmt" "reflect" "strings" ) type genericValues map[string][]string func (gv genericValues) Marshal(data any, tag string) (err error) { if gv == nil { gv = make(genericValues) } d := reflect.ValueOf(data) if d.Kind() == reflect.Pointer || d.Kind() == reflect.Interface { d = d.Elem() } if d.Kind() != reflect.Struct { err = fmt.Errorf("expected struct input for data") return } for i := 0; i < d.NumField(); i++ { key, ok := d.Type().Field(i).Tag.Lookup(tag) if !ok || key == "" { continue } v := make([]string, 0) val := d.Field(i) if val.Kind() == reflect.Pointer || val.Kind() == reflect.Interface { val = val.Elem() } if val.Kind() == reflect.Slice || val.Kind() == reflect.Array { for j := 0; j < val.Len(); j++ { item := val.Index(j) if item.Kind() == reflect.Pointer || item.Kind() == reflect.Interface { item = item.Elem() } v = append(v, fmt.Sprintf("%s", item.Interface())) } } else { v = append(v, fmt.Sprintf("%s", val.Interface())) } gv[key] = v } return } func (gv genericValues) Unmarshal(data any, tag string) (err error) { if gv == nil { err = fmt.Errorf("expected map to exist") return } d := reflect.ValueOf(data) if d.Kind() != reflect.Pointer || d.Kind() != reflect.Interface { err = fmt.Errorf("expected pointer for data") return } d = d.Elem() if d.Kind() != reflect.Struct { err = fmt.Errorf("expected struct input for data") return } for key, value := range gv { var v reflect.Value if len(value) == 1 { v = reflect.ValueOf(value[0]) } else { v = reflect.ValueOf(value) } for i := 0; i < d.NumField(); i++ { k, ok := d.Type().Field(i).Tag.Lookup(tag) if !ok || k != key { continue } val := d.Field(i) if val.Kind() == reflect.Pointer || val.Kind() == reflect.Interface { val = val.Elem() } if !val.CanSet() { err = fmt.Errorf("could not set value for %s", d.Type().Field(i).Name) } switch val.Kind() { case reflect.String: val.Set(reflect.ValueOf(strings.Join(value, "; "))) default: if v.CanConvert(val.Type()) { val.Set(v.Convert(val.Type())) } } } } return }