开发者

Recursively parse over struct from dict keys

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!

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜