Go - 使用相同的标记

时间:2016-07-08 00:42:47

标签: xml go encoding struct

我正在处理一个期望XML的API,其格式通常是这样的。

<receiver>
    <receiver_type>test</receiver_type>
    <hostnames>http://posttestserver.com</hostnames>
    <credentials>
      <credential>
        <name>app-id</name>
        <value>1234</value>
        <safe>true</safe>
      </credential>
      <credential>
        <name>app-secret</name>
        <value>5678</value>
      </credential>
    </credentials>
  </receiver>

因此,在我的Go代码中,我将这些结构用于我的函数并编组到XML结构中。请注意,不同的接收者可以拥有不同的凭证集。

type Receiver1 struct {
    XMLName      xml.Name             `xml:"receiver"`
    ReceiverType string               `xml:"receiver_type"`
    HostNames    string               `xml:"hostnames"`
    Credentials  Receiver1Credentials `xml:"credentials"`
}

type Receiver2 struct {
    XMLName      xml.Name             `xml:"receiver"`
    ReceiverType string               `xml:"receiver_type"`
    HostNames    string               `xml:"hostnames"`
    Credentials  Receiver2Credentials `xml:"credentials"`
}

type Receiver1Credentials struct {
    AppID     Credential `xml:"credential"`
    AppSecret Credential `xml:"credential"`
}

type Receiver2Credentials struct {
    UserName Credential `xml:"credential"`
    Password Credential `xml:"credential"`
    AppID    Credential `xml:"credential"`
}

type Credential struct {
    Name  string `xml:"name"`
    Value string `xml:"value"`
    Safe  bool   `xml:"safe"`
}

然而,这会产生Receiver1Credentials field "AppID" with tag "credential" conflicts with field "AppSecret" with tag "credential"行的运行时错误,这意味着我无法直接标记凭据字段。我尝试在Credential结构上使用字段XMLName xml.Name xml:"credential"(就像在Receiver结构上一样),但它会被Credentials结构上的标记覆盖。有谁知道如何解决这个问题?

1 个答案:

答案 0 :(得分:3)

要将数据编组为xml,您只需创建一个简单的接收器结构,对其进行初始化,然后调用xml.Marshal(...)

(请注意,要将credential嵌套到credentials中,需要将显式xml标记与字段相关联)

type Receiver struct {
    XMLName      xml.Name     `xml:"receiver"`
    ReceiverType string       `xml:"receiver_type"`
    HostNames    string       `xml:"hostnames"`
    Credentials  []Credential `xml:"credentials>credential"` // necessary to allow tag nesting
}

type Credential struct {
    Name  string `xml:"name"`
    Value string `xml:"value"`
    Safe  bool   `xml:"safe,omitempty"` // omitempty does not include the tag if if it's empty
}

现在您可以简单地初始化Receiver并将其编组为xml:

r := &Receiver{
        ReceiverType: "test",
        HostNames: "http://posttestserver.com",
        Credentials: []Credential{
            Credential{"app-id", "1234", true},
            Credential{"app-secret", "5678", false},
        },
    }
    a, _ := xml.MarshalIndent(r, "", "  ") // a is []byte containing xml encoded data

(工作示例:https://play.golang.org/p/JZcUUK9P1f

原始答案 - 将上述xml解组为接收器的方法

如果您可以避免将xml数据直接解析为Receiver[12]Credentials,则可以使用以下方法将xml数据解组为更简单的结构(ReceiverCredential):< / p>

receiver := &Receiver{}
xml.Unmarshal(xmlDataByteSlice, receiver)

这会在Credential上方存储所有receiver.Credentials个对象:

fmt.Println(receiver.Credentials)
// [{app-id 1234 true} {app-secret 5678 false}]

然后,您可以使用switch case上的receiver,Credential.Name相应地初始化Receiver[12]Credentials

工作示例:https://play.golang.org/p/jq3BrxKVo-