fatih / structtag

Parse and modify Go struct field tags
Other
633 stars 39 forks source link

Modifying Struct Tag #15

Closed D-sense closed 3 years ago

D-sense commented 3 years ago

Hi @fatih ,

Thanks for this amazing package. I believe this package may not offer exactly what I need, but I am wondering if it is possible to modify the value of a struct tag (not a struct field). Kindly take a look at the snippet below:


type VolumeData struct {
    State            string `mapstructure:"state" mapping:",ui"`
    VolumeId         string `mapstructure:"volume_id" mapping:",index,ui"`
    VolumeType       string `mapstructure:"volume_type" mapping:",index,ui"`
    AvailabilityZone string `mapstructure:"availability_zone" mapping:",index,ui"`
    Encrypted        bool   `mapstructure:"encrypted" mapping:",index,ui"`
}

func main() {
    vlm := VolumeData{
        State:            "adas",
        VolumeId:         "fddf",
        VolumeType:       "qq",
        AvailabilityZone: "xx",
        Encrypted:        false,
    }

    s := filterStruct2(vlm)
    fmt.Println(s)
}

func filterStructs(vlm VolumeData) *VolumeData {

    var yesIndex VolumeData

    t := reflect.TypeOf(vlm)

    // looping  through fields of the struct
    for i := 0; i < t.NumField(); i++ {
        field := t.Field(i)

        tags, err := structtag.Parse(string(field.Tag))
        if err != nil {
            return nil
        }

        if tag := field.Tag.Get(tagName); shouldIndex(tag) {
            mstruct := field.Tag.Get("mapstructure")
            switch mstruct {
            case "state":
                yesIndex.State = vlm.State
            case "volume_id":
                yesIndex.VolumeId = vlm.VolumeId
            case "volume_type":
                yesIndex.VolumeType = vlm.VolumeType
            case "availability_zone":
                yesIndex.AvailabilityZone = vlm.AvailabilityZone
            case "encrypted":
                yesIndex.Encrypted = vlm.Encrypted
            }
        } else {

            // change struct tag's value to `mapstructure:",omitempty"`
            jsonTag, err := tags.Get("mapstructure")
            if err != nil {
                panic(err)
            }

            // change existing tag
            jsonTag.Name = ",omitempty"
            jsonTag.Options = nil
            tags.Set(jsonTag)
        }

        field.Tag = reflect.StructTag(tags.String())
    }

    n := reflect.TypeOf(vlm)

    for i := 0; i < n.NumField(); i++ {
        field := t.Field(i)
        // I expect the struct tag for the first element to be `,omitempty`
        fmt.Println("......", field.Tag)
    }

    return &yesIndex
}
fatih commented 3 years ago

I think that's an anti-pattern, but look at this example that shows how it can be done:

https://play.golang.org/p/QNArOeqy94

Also, there is a package called retag that could be useful for you:

https://pkg.go.dev/github.com/sevlyar/retag

I'm closing this issue as I don't think there is much to do here. Thank you.