
本文详解如何使用 Go 的 encoding/xml 和 encoding/json 包,将含嵌套标签(如 ...)的 XML 数据精准映射为语义清晰、层级合理的 JSON,避免字段扁平化或键名污染。
本文详解如何使用 go 的 `encoding/xml` 和 `encoding/json` 包,将含嵌套标签(如 `
在 Go 中实现 XML 到 JSON 的转换,关键不在于“硬编码路径”,而在于通过结构体标签精确建模 XML 层级关系,并确保 JSON 输出结构与之严格对齐。你遇到的问题——"features > feature": "conditions" 这类错误键名,根源在于 reportTypeJson.Features 被定义为 string 类型并错误使用了含空格/符号的 JSON tag(如 "features feature"),导致 Go 将其序列化为非法 JSON 键;同时,XML 解析层也未正确反映嵌套结构。
✅ 正确建模:XML 与 JSON 结构需双向一致
首先,修正 XML 解析结构体,使其能准确捕获嵌套节点:
type reportType struct {
Version xml.CharData `xml:"version"`
TermsOfService xml.CharData `xml:"termsofService"`
Features featureNode `xml:"features"` // ← 关键:用自定义结构体承接嵌套节点
Zip xml.CharData `xml:"current_observation>display_location>zip"`
Problem myErrorType `xml:"error"`
}
// featureNode 映射 <features><feature>value</feature></features>
type featureNode struct {
Feature string `xml:"feature"`
}
type myErrorType struct {
TypeOfError xml.CharData `xml:"type"`
Description xml.CharData `xml:"description"` // 修正拼写:Desciption → Description
}
⚠️ 注意:xml:"features" 表示该字段对应
标签整体,其内部结构由 featureNode 定义,而非直接用 xml:"features>feature" 提取文本——后者会跳过父节点语义,导致 JSON 层无法构建对象。
接着,定义 语义匹配的 JSON 输出结构体:
type ReportJSON struct {
Version string `json:"version"`
TermsOfService string `json:"termsofService"`
Features Features `json:"features"` // ← 对应 features 对象,非字符串
Zip string `json:"current_observation_display_location_zip"` // 建议简化 JSON key(避免 > 符号)
}
type Features struct {
Feature string `json:"feature"`
}
✅ 优势:Features 是一个命名结构体,json:"features" 确保生成 "features": { "feature": "conditions" },完全符合预期。
? 安全转换:从 XML 结构体到 JSON 结构体
转换时需显式赋值,保持类型安全:
// 解析 XML
var report reportType
err := xml.Unmarshal(body, &report)
doErr(err, "XML unmarshal failed")
// 构建 JSON 结构体实例
output := ReportJSON{
Version: string(report.Version),
TermsOfService: string(report.TermsOfService),
Features: Features{
Feature: string(report.Features.Feature), // ← 深度访问嵌套字段
},
Zip: string(report.Zip),
}
// 序列化为格式化 JSON
data, err := json.MarshalIndent(output, "", " ")
doErr(err, "JSON marshal failed")
fmt.Printf("JSON output:\n%s\n", data)
? 进阶提示:支持多值 features(如 a b )
若
type featureNode struct {
Features []string `xml:"feature"` // 自动收集所有 <feature> 文本
}
type Features struct {
Feature []string `json:"feature"`
}</feature>
此时 XML 解析会自动填充 []string{"conditions", "forecast", ...},JSON 输出即为 "features": { "feature": ["conditions", "forecast"] }。
✅ 总结
- ❌ 避免将嵌套 XML 节点强行映射为 string 并滥用含特殊字符的 JSON tag;
- ✅ 使用嵌套结构体(如 featureNode)解析 XML,再通过同名/同构结构体(如 Features)生成 JSON;
- ✅ JSON key 应简洁规范(如 current_observation_display_location_zip),避免 > 或空格;
- ✅ 所有 xml.CharData 转 string 时需显式调用 string(),且注意 UTF-8 安全性;
- ✅ 多值场景优先使用切片([]string)而非 map[string]string——更符合 XML 顺序语义,也更易维护。
通过结构化建模而非字符串拼接,你的 Go 程序即可健壮、可扩展地处理任意深度的 XML→JSON 转换需求。











