简体   繁体   中英

How to assign modified value of nested struct using reflection to struct

I have this structure

type Library struct {
    Book            Book           
    Owner           Owner           
    Editorial       Editorial
}

and I had to modify one of the tags of the auto-generated Book structure from category to categoryID .

type Book struct {
    ID             string           `json:"id"`
    Title          string           `json:"title"`
    Description    string           `json:"description"`
    Category       string           `json:"category"`
} 

My question is, after modifying those fields and getting correct structure of Book, how can I set it to become the new struct in Library.Book ?

My code:

func renameTags(p any, m map[string]string) any {

    rv := reflect.ValueOf(p)
    re := rv.Elem()
    rt := rv.Elem().Type()

    fields := make([]reflect.StructField, rt.NumField())
    for i := range fields {
        f := rt.Field(i) // Book i == 0

        if f.Type.Kind() == reflect.Struct && f.Type.Name() == "Book" {
            fields2 := make([]reflect.StructField, f.Type.NumField()) // f == Book
            for j := 0; j < f.Type.NumField(); j++ {
                subField := f.Type.Field(j)
                tag := subField.Tag.Get("json")
                if v, ok := m[tag]; ok {
                    subField.Tag = reflect.StructTag(`json:"` + v + `"`)
                }
                fields2[j] = subField // change structure of Book
            }

            // here how to append new structure to f ?

            //kk := reflect.StructOf(fields2).Elem()

        }

        fields[i] = f
    }

    st := reflect.StructOf(fields)
    return rv.Convert(reflect.PtrTo(st)).Interface()
}

Any advice will be very much appreciated, thanks!

You can use reflect.New to create a new instance of the modified structure, then assign the value to the appropriate field in the original struct. Here's an updated code:

func renameTags(p any, m map[string]string) any {

    rv := reflect.ValueOf(p)
    re := rv.Elem()
    rt := rv.Elem().Type()

    fields := make([]reflect.StructField, rt.NumField())
    for i := range fields {
        f := rt.Field(i) // Book i == 0

        if f.Type.Kind() == reflect.Struct && f.Type.Name() == "Book" {
            fields2 := make([]reflect.StructField, f.Type.NumField()) // f == Book
            for j := 0; j < f.Type.NumField(); j++ {
                subField := f.Type.Field(j)
                tag := subField.Tag.Get("json")
                if v, ok := m[tag]; ok {
                    subField.Tag = reflect.StructTag(`json:"` + v + `"`)
                }
                fields2[j] = subField // change structure of Book
            }

            newStruct := reflect.New(reflect.StructOf(fields2))
            re.Field(i).Set(newStruct)
        }

        fields[i] = f
    }

    st := reflect.StructOf(fields)
    return rv.Convert(reflect.PtrTo(st)).Interface()
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM