代码之家  ›  专栏  ›  技术社区  ›  user_78361084

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

go
  •  0
  • user_78361084  · 技术社区  · 5 年前

    假设我有以下几点:

    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 回复  |  直到 5 年前
        1
  •  2
  •   VonC    5 年前

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

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

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

        2
  •  1
  •   Uvelichitel    5 年前

    也可以在运行时使用 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