虽然 JSON 已经是主流,但 XML 在一些老系统或者特定行业里还是占有一席之地的。Gin 返回 XML 响应同样简单。
使用 c.XML() 方法返回 XML 格式数据:
package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
r.GET("/xml", func(c *gin.Context) {
c.XML(http.StatusOK, gin.H{
"name": "张三",
"age": 25,
"city": "北京",
})
})
r.Run(":8080")
}
返回的结果类似:
<map>
<name>张三</name>
<age>25</age>
<city>北京</city>
</map>
和 JSON 一样,用结构体可以获得更好的类型控制和字段命名:
type UserXML struct {
XMLName xml.Name `xml:"user"`
ID int `xml:"id,attr"`
Name string `xml:"name"`
Email string `xml:"email"`
Active bool `xml:"active"`
}
r.GET("/user/xml", func(c *gin.Context) {
user := UserXML{
ID: 1,
Name: "张三",
Email: "zhangsan@example.com",
Active: true,
}
c.XML(http.StatusOK, user)
})
返回结果:
<user id="1">
<name>张三</name>
<email>zhangsan@example.com</email>
<active>true</active>
</user>
通过 xml tag 可以灵活控制 XML 的结构,比如 xml:"id,attr" 把字段作为属性,xml:",chardata" 把字段作为元素的文本内容。
XML 经常需要嵌套结构,这在 Go 里也很好处理:
type Address struct {
City string `xml:"city"`
Street string `xml:"street"`
ZipCode string `xml:"zip_code"`
}
type Person struct {
XMLName xml.Name `xml:"person"`
Name string `xml:"name"`
Address Address `xml:"address"`
}
r.GET("/person", func(c *gin.Context) {
person := Person{
Name: "张三",
Address: Address{
City: "北京",
Street: "长安街1号",
ZipCode: "100000",
},
}
c.XML(http.StatusOK, person)
})
返回列表数据时,需要定义一个包装结构:
type User struct {
ID int `xml:"id"`
Name string `xml:"name"`
}
type UserList struct {
XMLName xml.Name `xml:"users"`
Users []User `xml:"user"`
}
r.GET("/users/xml", func(c *gin.Context) {
users := UserList{
Users: []User{
{ID: 1, Name: "张三"},
{ID: 2, Name: "李四"},
{ID: 3, Name: "王五"},
},
}
c.XML(http.StatusOK, users)
})
有时候需要明确指定响应的 Content-Type:
r.GET("/custom/xml", func(c *gin.Context) {
c.Header("Content-Type", "application/xml; charset=utf-8")
c.XML(http.StatusOK, gin.H{
"message": "自定义 Content-Type",
})
})
Gin 的 XML 响应使用起来和 JSON 几乎一样,主要区别在于结构体 tag 使用 xml 而不是 json。如果你的 API 需要对接老系统或者特定行业标准,XML 响应就能派上用场了。