条件(动态)结构标签

时间:2019-05-26 14:44:04

标签: go

我正在尝试在Go中解析一些xml文档。为此,我需要定义一些结构,而我的struct标签取决于特定条件。

想象下面的代码(即使我知道它不会工作)

if someCondition {
    type MyType struct {
        // some common fields
        Date    []string `xml:"value"`
    }
} else {
    type MyType struct {
        // some common fields
        Date    []string `xml:"anotherValue"`
    }
}

var t MyType
// do the unmarshalling ...

问题在于这两个结构具有许多共同的字段。唯一的区别是在一个字段中,我想防止重复。我该如何解决这个问题?

3 个答案:

答案 0 :(得分:2)

您使用不同类型取消编组。基本上,您编写了两次编组代码,然后运行第一个版本或第二个版本。没有动态的解决方案。

答案 1 :(得分:0)

最简单的方法可能是处理所有可能的字段并进行一些后处理。

例如:

type MyType struct {
    DateField1    []string `xml:"value"`
    DateField2    []string `xml:"anotherValue"`
}

// After parsing, you have two options:

// Option 1: re-assign one field onto another:
if !someCondition {
    parsed.DateField1 = parsed.DateField2
    parsed.DateField2 = nil
}

// Option 2: use the above as an intermediate struct, the final being:
type MyFinalType struct {
    Date    []string `xml:"value"`
}

if someCondition {
    final.Date = parsed.DateField1
} else {
    final.Date = parsed.DateField2
}

注意:如果消息足够不同,则可能需要完全不同的类型进行解析。后处理可以从任何一个生成最终结构。

答案 2 :(得分:0)

如前所述,您必须复制该字段。问题是复制应该在哪里。

如果只是多个字段中的一个,则一种选择是使用嵌入和字段阴影化:

type MyType struct {
    Date    []string `xml:"value"`
    // many other fields
}

然后Date使用其他字段名称时:

type MyOtherType struct {
    MyType // Embed the original type for all other fields
    Date     []string `xml:"anotherValue"`
}

然后将MyOtherType解组后,很容易将Date的值移动到原始结构中:

type data MyOtherType
err := json.Unmarshal(..., &data)
data.MyType.Date = data.Date
return data.MyType // will of MyType, and fully populated

请注意,这仅适用于封送处理。如果您还需要封送数据,则可以使用类似的技巧,但必须彻底扭转其机制。