doushuo2834 2016-07-08 00:42
浏览 57
已采纳

Go-使用相同标签编码结构字段

I am dealing with an API that is expecting XML that is generally formatted like so.

<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>

Therefore, in my Go code, I made these structs to use in my functions and marshal into the XML structure. Note that different receivers can have different sets of credentials.

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"`
}

However this produces runtime errors along the lines of Receiver1Credentials field "AppID" with tag "credential" conflicts with field "AppSecret" with tag "credential" meaning that I can't directly tag the Credentials fields the same thing. I've tried using a field XMLName xml.Name xml:"credential" (like on the Receiver structs) on the Credential struct, but it gets overwritten by the tag on the Credentials structs. Does anyone know how I could work around this?

  • 写回答

1条回答

  • duanen19871021 2016-07-08 08:05
    关注

    To Marshal the data into xml, you can simply create a simple receiver struct, initialize it, and call xml.Marshal(...).

    (Note that to nest credential into credentials, explicit xml tag needs to be associated with the fields)

    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
    }
    

    Now you can simply initialize a Receiver and marshal it into 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
    

    (working example: https://play.golang.org/p/JZcUUK9P1f)

    Original answer - method to unmarshal the above xml into receiver

    If you can avoid parsing the xml data directly into Receiver[12]Credentials, you can unmarshal the xml data into a much simpler structure (Receiver and Credential above) using the following method:

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

    This would store all the Credential objects in receiver.Credentials above:

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

    You can then perhaps use a switch case on receiver,Credential.Name to initialize Receiver[12]Credentials accordingly.

    Working example: https://play.golang.org/p/jq3BrxKVo-

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 jupyterthemes 设置完毕后没有效果
  • ¥15 matlab图像高斯低通滤波
  • ¥15 针对曲面部件的制孔路径规划,大家有什么思路吗
  • ¥15 钢筋实图交点识别,机器视觉代码
  • ¥15 如何在Linux系统中,但是在window系统上idea里面可以正常运行?(相关搜索:jar包)
  • ¥50 400g qsfp 光模块iphy方案
  • ¥15 两块ADC0804用proteus仿真时,出现异常
  • ¥15 关于风控系统,如何去选择
  • ¥15 这款软件是什么?需要能满足我的需求
  • ¥15 SpringSecurityOauth2登陆前后request不一致