I am trying to recursively parse a form data dictionary into an embedded struct. It is kindof working, but eventually only one field gets set. I figured that the field keeps being overridden by the old struct, but need some help finding the solution.
Entrypoint of the function:
func FormDataToStruct(data map[string]string, s any) {
// Parse the form data into the struct
v := reflect.ValueOf(s)
if v.Kind() == reflect.Ptr {
v = v.Elem()
}
if v.Kind() != reflect.Struct {
panic("not a struct")
}
formParse(data, v, s)
}
Set the values on the topmost struct:
func formParse(data map[string]string, v reflect.Value, s any) {
for key, value := range data {
if hasField(v, key) {
println("Found field: " + key)
var val, err = TransformValue(s, key, value)
if err != nil {
panic(err)
}
SetValue(s, key, val)
delete(data, key)
}
}
// Set values of inner structs
for key, value := range data {
keys := strings.Split(key, "_")
// Parse the inner struct recursively with another function
recurseKeys(keys, value, v, s, s)
}
}
Struct looks like this:
type Me struct {
Name string
Age int
Friend struct {
Name string
Age int
}
}
Form data to parse looks like this:
map[name:John age:20 friend_name:Jane friend_age:20]
func recurseKeys(keys []string, value string, v reflect.Value, s any, parent any) {
if len(keys) == 1 {
// We are at the end of the keys
// Set the value
var val, err = TransformValue(s, keys[0], value)
if err != nil {
panic(err)
}
SetValue(s, keys[0], val)
return
}
// We are not at the end of the keys
// We need to iterate over the struct
for i := 0; i < v.NumField(); i++ {
if strings.EqualFold(v.Type().Field(i).Name, keys[0]) {
// We found the field
// Recurse with the next key
newS := reflect.New(v.Field(i).Type())
recurseKeys(keys[1:], value, v.Field(i), newS.Interface(), parent)
// Check if the field on the old struct is a pointer, if it is, we need to set the pointer
// If it is not a pointer, we need to set the value
if v.Field(i).Kind() == reflect.Ptr {
// Check if newS is a pointer
if newS.Kind() == reflect.Ptr {
v.Field(i).Set(newS)
} else {
v.Field(i).Set(newS.Elem())
}
} else {
// Check if newS is a pointer
if newS.Kind() == reflect.Ptr {
v.Field(i).Set(newS.Elem())
} else {
v.Field(i).Set(newS)
}
}
}
}
}
Running the above form data through the struct would result in the following output:
println(meInstance)
// {John 20 {Jane 0}}
开发者_开发问答
Any help is very much appreciated!
精彩评论