如何以非手动方式更改所有struct标记的前缀?

时间:2019-01-16 02:38:18

标签: go

假设我有以下内容:

type My struct{
  First string `xml:"first"`
  Last string `xml:"name"`
  ...many more tags...
}

我想将所有标签的前缀更改为“ mycustomtag”。我见过https://stackoverflow.com/a/42549826/522962,但这描述了一种手动方式,其中您手动定义了带有标签的第二个结构。我如何自动这样做?

例如我想在下面给出类似的内容,但是由于有很多字段,我该怎么做,所以我不必手动进行操作:

// how do I do the next part automagically????
func (m *My) MarshalJSON() ([]byte, error) {
    type alias struct {
        First string `mycustomtag:"first"`
        Last string `mycustomtag:"name"`
        ...many more tags...
    }
    var a alias = alias(*m)
    return json.Marshal(&a)
}

2 个答案:

答案 0 :(得分:2)

如果这不是在运行时,而是静态地修改代码源,则可以使用fatih/gomodifytags

请参见“ Writing a Go Tool to Parse and Modify Struct Tags

  

结构字段标记是编码/解码类型的重要组成部分,尤其是在使用诸如encoding / json之类的包时。
  但是,修改标签是重复的,麻烦的,而且容易出现人为错误。
  我们可以使用专门为此目的而编写的自动化工具来轻松修改标签。

答案 1 :(得分:1)

如果需要,您还可以在运行时使用reflect进行操作。

func (m *My) MarshalJSON() ([]byte, error) {
    oldtype := reflect.TypeOf(*m)
    fields := make([]reflect.StructField, oldtype.NumField())
    for i := 0; i < oldtype.NumField(); i++ {
        field := oldtype.Field(i)
        if _, ok := field.Tag.Lookup("xml"); ok {
            field.Tag = reflect.StructTag(strings.Replace(string(field.Tag), "xml", "json", 1))
        }

        fields[i] = field
    }
    newtype := reflect.StructOf(fields)
    a := reflect.ValueOf(*m).Convert(newtype).Interface()
    return json.Marshal(&a)
}

Working example