Golang 中 JSON 和 XML 解析与生成
·

Golang 中 JSON 和 XML 解析与生成
JSON 处理
JSON 解析
在 Go 语言中,encoding/json 包提供了强大的 JSON 处理能力。JSON 解析主要有两种方式:
- 解析到结构体(推荐方式):
type Person struct {
Name string `json:"name"` // 使用标签指定 JSON 字段名
Age int `json:"age"`
Address string `json:"address,omitempty"` // omitempty 表示字段为空时忽略
}
func main() {
jsonStr := `{"name":"张三","age":30}`
var p Person
err := json.Unmarshal([]byte(jsonStr), &p)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%+v\n", p) // 输出: {Name:张三 Age:30 Address:}
}
- 解析到 map(适用于动态结构):
func main() {
jsonStr := `{"name":"李四","age":25,"hobbies":["reading","swimming"]}`
var data map[string]interface{}
err := json.Unmarshal([]byte(jsonStr), &data)
if err != nil {
log.Fatal(err)
}
fmt.Println(data["name"]) // 输出: 李四
fmt.Println(data["hobbies"].([]interface{})[0]) // 输出: reading
}
JSON 生成
将 Go 数据结构转为 JSON 同样简单:
func main() {
p := Person{
Name: "王五",
Age: 28,
}
jsonData, err := json.Marshal(p)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(jsonData)) // 输出: {"name":"王五","age":28}
// 格式化输出
jsonData, _ = json.MarshalIndent(p, "", " ")
fmt.Println(string(jsonData))
/*
输出:
{
"name": "王五",
"age": 28
}
*/
}
XML 处理
XML 解析
Go 标准库中的 encoding/xml 包提供了 XML 处理功能:
- 解析到结构体:
type Employee struct {
XMLName xml.Name `xml:"employee"`
ID int `xml:"id,attr"` // 解析为属性
FirstName string `xml:"name>first"` // 嵌套元素
LastName string `xml:"name>last"`
Position string `xml:"position"`
Salary float64 `xml:"salary"`
}
func main() {
xmlStr := `
<employee id="1001">
<name>
<first>诸葛</first>
<last>亮</last>
</name>
<position>丞相</position>
<salary>9999.99</salary>
</employee>`
var emp Employee
err := xml.Unmarshal([]byte(xmlStr), &emp)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%+v\n", emp) // 输出: {XMLName:{Space: Local:employee} ID:1001 FirstName:诸葛 LastName:亮 Position:丞相 Salary:9999.99}
}
- 流式解析(适用于大文件):
func main() {
xmlFile, err := os.Open("employees.xml")
if err != nil {
log.Fatal(err)
}
defer xmlFile.Close()
decoder := xml.NewDecoder(xmlFile)
for {
// 逐个解析 token
t, err := decoder.Token()
if err == io.EOF {
break
}
if err != nil {
log.Fatal(err)
}
switch se := t.(type) {
case xml.StartElement:
if se.Name.Local == "employee" {
var emp Employee
decoder.DecodeElement(&emp, &se)
fmt.Println(emp)
}
}
}
}
XML 生成
将 Go 结构体转为 XML:
func main() {
emp := Employee{
ID: 1002,
FirstName: "周",
LastName: "瑜",
Position: "都督",
Salary: 8888.88,
}
xmlData, err := xml.MarshalIndent(emp, "", " ")
if err != nil {
log.Fatal(err)
}
fmt.Println(string(xmlData))
/*
输出:
<employee id="1002">
<name>
<first>周</first>
<last>瑜</last>
</name>
<position>都督</position>
<salary>8888.88</salary>
</employee>
*/
// 添加 XML 头
xmlData = []byte(xml.Header + string(xmlData))
fmt.Println(string(xmlData))
}
实际应用场景
- Web API 开发:
- 接收请求数据:
- 处理客户端发送的 JSON/XML 格式的 HTTP 请求
- 使用标准库或第三方库(如 encoding/json、encoding/xml)解析请求体
- 示例:解析用户注册请求
{"username":"test","password":"123456"}
- 返回响应:
- 将业务数据序列化为 JSON/XML 格式响应
- 设置正确的 Content-Type 响应头(application/json 或 application/xml)
- 示例:返回用户信息
{"id":1,"name":"张三","age":25}
- 配置文件处理:
- 解析配置文件:
- 读取项目的 config.json/config.xml 文件
- 解析为配置结构体供程序使用
- 支持热更新配置(监听文件变化自动重新加载)
- 备份配置:
- 定期将当前配置序列化为 JSON/XML 格式备份
- 支持版本控制(如 config_v1.json, config_v2.json)
- 数据交换:
- 系统间通信:
- 通过 HTTP/RPC 等方式在微服务间传递 JSON/XML 数据
- 定义统一的数据交换格式规范
- 第三方 API 集成:
- 对接微信支付、支付宝等第三方平台的 API
- 处理不同格式的请求/响应(如微信使用 XML,支付宝使用 JSON)
- 数据持久化:
- 数据存储:
- 将内存中的数据结构序列化为 JSON/XML 保存到本地文件
- 支持压缩存储以减少磁盘空间占用
- 数据恢复:
- 从存储文件中读取数据并反序列化
- 处理数据版本兼容性问题
性能优化建议
- 处理大型数据:
- 流式处理:
- 使用 json.Decoder 逐步解析大型 JSON 文件
- 使用 xml.Decoder 处理 XML 数据流
- 避免一次性加载整个文件导致内存溢出
- 示例代码:
decoder := json.NewDecoder(largeFile) for decoder.More() { var item DataItem if err := decoder.Decode(&item); err != nil { // 处理错误 } // 处理item }
- 实例复用:
- 编码器复用:
- 在 HTTP 服务中复用全局的 json.Encoder 实例
- 通过 sync.Pool 管理编码器对象池
- 解码器复用:
- 对高频请求创建长期存活的解码器实例
- 避免重复创建带来的性能损耗
- 第三方库优化:
- jsoniter:
- 替换标准库实现,提升 2-3 倍性能
- 支持流式处理和大数据量场景
- 示例:
import "github.com/json-iterator/go" var json = jsoniter.ConfigCompatibleWithStandardLibrary
- 其他优化库:
- fastjson 用于极致性能场景
- easyjson 通过代码生成优化
- 内存优化:
- 原始字节操作:
- 使用 json.RawMessage 延迟解析
- 直接操作 JSON 字节数据避免完整反序列化
- 示例:
type Message struct { Header json.RawMessage Body json.RawMessage }
- 内存池技术:
- 使用 sync.Pool 重用缓冲区
- 减少 GC 压力
常见问题处理
- 处理动态字段:
type DynamicData struct {
Data map[string]interface{} `json:",inline"` // 处理未知字段
}
- 自定义时间格式:
type Event struct {
Time CustomTime `json:"time"`
}
type CustomTime struct {
time.Time
}
func (ct *CustomTime) UnmarshalJSON(b []byte) error {
s := strings.Trim(string(b), `"`)
t, err := time.Parse("2006-01-02 15:04:05", s)
if err != nil {
return err
}
ct.Time = t
return nil
}
func (ct CustomTime) MarshalJSON() ([]byte, error) {
return []byte(`"` + ct.Time.Format("2006-01-02 15:04:05") + `"`), nil
}
- 处理特殊字符:
// 在 XML 中处理 CDATA
type Description struct {
Content string `xml:",cdata"`
}
更多推荐


所有评论(0)