在 Go 中处理 JSON:数据解析与序列化

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

Go 语言中 JSON 处理入门

JSON(JavaScript 对象表示法)是一种轻量级数据交换格式,广泛应用于 Web 应用、API 和微服务中。Go 语言(Golang)提供了强大的内置库 encoding/json,可以轻松实现数据的解析(反序列化)和序列化。在本文中,我们将深入探讨如何在 Go 中处理 JSON,涵盖主要函数、结构体以及最佳实践。



序列化与反序列化基础

序列化是将 Go 数据结构(如结构体或切片)转换为 JSON 字符串的过程。反序列化则是相反的过程——将 JSON 转换为 Go 结构体。



序列化(Marshal)

序列化使用 json.Marshal() 函数。它接收一个 Go 值,并返回包含 JSON 表示的字节切片([]byte)。

package main

import ( "encoding/json" "fmt")

type User struct { Name string `json:"name"` Age int `json:"age"` Email string `json:"email,omitempty"`}

func main() { user := User{Name: "Alexey", Age: 30, Email: "alex@example.com"} jsonData, err := json.Marshal(user) if err != nil { fmt.Println("Serialization error:", err) return } fmt.Println(string(jsonData)) // Output: {"name":"Alexey","age":30,"email":"alex@example.com"}

注意标签 json:"field_name"。它们允许你控制 JSON 中的键名,并添加选项,如 omitempty(如果字段为空则跳过)。



反序列化(Unmarshal)

要将 JSON 解析为 Go 结构体,使用 json.Unmarshal() 函数。它接收一个字节切片和一个指向目标结构体的指针。

func main() {    jsonString := `{"name":"Maria","age":25,"email":"maria@example.com"}`    var user User    err := json.Unmarshal([]byte(jsonString), &user)    if err != nil {        fmt.Println("Parsing error:", err)        return    }    fmt.Printf("Name: %s, Age: %d, Email: %s", user.Name, user.Age, user.Email)}

重要提示:结构体必须预先定义,且其字段必须与 JSON 键名对应(考虑标签)。



处理任意 JSON 对象

有时 JSON 结构未知或过于复杂。在这种情况下,可以使用 map[string]interface{} 或 interface{}。



使用 map[string]interface{}

func main() {    jsonString := `{"name":"Ivan","age":35,"address":{"city":"Moscow","street":"Lenina"}}`    var result map[string]interface{}    err := json.Unmarshal([]byte(jsonString), &result)    if err != nil {        fmt.Println("Error:", err)        return    }    fmt.Println(result["name"]) // Ivan    fmt.Println(result["age"])  // 35 (type float64)    // 对于嵌套对象,需要进行类型断言    address := result["address"].(map[string]interface{})    fmt.Println(address["city"]) // Moscow}

这种方法的缺点是需要手动进行类型断言(.(map[string]interface{})),如果类型不匹配,可能导致 panic。



使用 json.RawMessage

如果需要延迟解析 JSON 的一部分,可以使用 json.RawMessage。这允许你先解析主结构体,然后单独处理嵌套数据。

type Response struct {    Status string          `json:"status"`    Data   json.RawMessage `json:"data"`}

func main() { jsonString := `{"status":"ok","data":{"user":"Peter","score":100}}` var resp Response json.Unmarshal([]byte(jsonString), &resp)

// 现在可以单独解析 Data var userData map[string]interface{} json.Unm

博客

书籍推荐