如何正确使用 Go 的 encoding/xml 包进行序列化与反序列化

如何正确使用 Go 的 encoding/xml 包进行序列化与反序列化

本文详解 go 中 `encoding/xml` 包的典型误用:将 xml 字节流错误地交由 `json.unmarshal` 解析,导致“invalid character ‘

在 Go 中,encoding/xml 和 encoding/json 是两套独立的序列化/反序列化机制,不可混用。问题中的核心错误在于:先用 xml.Marshal() 生成 XML 格式字节(如 1),却调用 json.Unmarshal() 去解析——而 JSON 解析器遇到起始字符

✅ 正确做法是:Marshal 与 Unmarshal 必须使用同一编码包。修复只需一行:

// ❌ 错误:用 json.Unmarshal 解析 XML 数据
err = json.Unmarshal(data, &pXml)

// ✅ 正确:用 xml.Unmarshal 解析 XML 数据
err = xml.Unmarshal(data, &pXml)

此外,为确保字段可被 XML 包正确处理,还需注意以下关键点:

  • 导出性要求:XML 只能序列化/反序列化首字母大写的导出字段(如 X, Y, Names),小写字段(如 z)会被忽略(这与 JSON 行为一致);
  • 切片字段支持:[]string 类型可直接映射为多个同名 XML 元素(如 BobAlice),无需额外标签;
  • 可选:添加 XML 标签优化输出(推荐):
type Point struct {
    X     int      `xml:"x"`           // 自定义元素名
    Y     int      `xml:"y"`
    Names []string `xml:"name"`        // 更语义化的标签名
}

完整可运行示例:

微撰

微撰

AI智能写作平台

下载

package main

import (
    "encoding/xml"
    "fmt"
)

type Point struct {
    X, Y  int
    z     int // 小写字段 → 被忽略
    Names []string
}

func main() {
    p := Point{X: 1, Y: 2, Names: []string{"Bob", "Alice"}}

    // 序列化为 XML
    data, err := xml.Marshal(p)
    if err != nil {
        panic(err)
    }
    fmt.Printf("XML: %s/n", string(data))

    // ✅ 正确:用 xml.Unmarshal 反序列化
    var pXml Point
    err = xml.Unmarshal(data, &pXml)
    if err != nil {
        panic(err) // 此处不再报错
    }
    fmt.Printf("Unmarshalled XML: %+v/n", pXml)
}

? 注意事项总结

  • 永远匹配 Marshal/Unmarshal 所属包:xml.Marshal ↔ xml.Unmarshal,json.Marshal ↔ json.Unmarshal;
  • XML 默认以结构体名作为根元素(如 ),可通过 xml:”name,attr” 等标签精细控制;
  • 若需兼容 HTTP 响应等带 XML 声明()或注释的文档,xml.Unmarshal 可自动跳过前置内容;
  • 对于含命名空间、CDATA 或复杂嵌套的 XML,建议结合 xml.Name 字段和自定义 UnmarshalXML 方法处理。

遵循以上原则,即可安全、高效地在 Go 中完成 XML 的双向数据绑定。

https://www.php.cn/faq/1964886.html

发表回复

Your email address will not be published. Required fields are marked *