ZetCode

Go JSON

最后修改日期:2025 年 5 月 4 日

在本文中,我们将展示如何在 Golang 中处理 JSON 数据。

JSON

JSON(JavaScript Object Notation)是一种广泛使用的轻量级数据交换格式,可促进结构化数据交换。JSON 旨在易于人类阅读,同时易于机器解析和生成,已成为 Web 开发、API 和配置文件中数据序列化的标准。

JSON 的官方 Internet 媒体类型为 application/json,确保不同系统之间数据处理的一致性。JSON 文件通常使用 .json 文件名扩展名。

Go 中的 JSON

Go 通过 encoding/json 包提供了对 JSON 的内置支持,该包提供了高效的 JSON 数据编码和解码函数。一些关键操作包括

JSON 在现代软件开发中起着至关重要的作用,它能够实现应用程序和服务之间的无缝通信。其简洁性以及 Go 的高效处理机制,使其成为结构化数据表示的理想选择。

Go 编码为 JSON

Marshal 函数将数据编码为 JSON。

encoding.go
package main

import (
    "encoding/json"
    "fmt"
    "log"
)

type User struct {
    Id         int
    Name       string
    Occupation string
}

func main() {

    u1 := User{1, "John Doe", "gardener"}

    json_data, err := json.Marshal(u1)

    if err != nil {

        log.Fatal(err)
    }

    fmt.Println(string(json_data))

    users := []User{
        {Id: 2, Name: "Roger Roe", Occupation: "driver"},
        {Id: 3, Name: "Lucy Smith", Occupation: "teacher"},
        {Id: 4, Name: "David Brown", Occupation: "programmer"},
    }

    json_data2, err := json.Marshal(users)

    if err != nil {

        log.Fatal(err)
    }

    fmt.Println(string(json_data2))
}

在代码示例中,我们将 Go 结构体和结构体切片转换为 JSON 格式。

type User struct {
    Id         int
    Name       string
    Occupation string
}

我们声明 User 结构体。

u1 := User{1, "John Doe", "gardener"}

我们创建结构体实例。

json_data, err := json.Marshal(u1)

我们使用 Marshalu1 结构体编码为 JSON。

fmt.Println(string(json_data))

由于 json_data 是一个字节数组,我们使用 string 函数将其转换为字符串。

users := []User{
    {Id: 2, Name: "Roger Roe", Occupation: "driver"},
    {Id: 3, Name: "Lucy Smith", Occupation: "teacher"},
    {Id: 4, Name: "David Brown", Occupation: "programmer"},
}

我们有一个用户切片。

json_data2, err := json.Marshal(users)

我们使用 Marshal 编码用户切片。

fmt.Println(string(json_data2))

我们打印编码后的切片。

$ go run encoding.go 
{"Id":1,"Name":"John Doe","Occupation":"gardener"}
[{"Id":2,"Name":"Roger Roe","Occupation":"driver"},{"Id":3,"Name":"Lucy Smith","Occupation":"teacher"},
{"Id":4,"Name":"David Brown","Occupation":"programmer"}]

Go 解码为 JSON

Unmarshal 函数将 JSON 数据解码为 Go 值。

decoding.go
package main

import (
    "encoding/json"
    "fmt"
    "log"
)

type User struct {
    Id         int
    Name       string
    Occupation string
}

func main() {

    var u1 User

    data := []byte(`{
        "Id" : 1,
        "Name": "John Doe",
        "Occupation": "gardener"
    }`)

    err := json.Unmarshal(data, &u1)

    if err != nil {

        log.Fatal(err)
    }

    fmt.Println("Struct is:", u1)
    fmt.Printf("%s is a %s.\n", u1.Name, u1.Occupation)

    var u2 []User

    data2 := []byte(`
    [
        {"Id":2,"Name":"Roger Roe","Occupation":"driver"},
        {"Id":3,"Name":"Lucy Smith","Occupation":"teacher"},
        {"Id":4,"Name":"David Brown","Occupation":"programmer"}
    ]`)

    err2 := json.Unmarshal(data2, &u2)

    if err2 != nil {

        log.Fatal(err2)
    }

    for i := range u2 {

        fmt.Println(u2[i])
    }
}

我们将 JSON 字符串解码为 Go 结构体和结构体切片。

data := []byte(`{
    "Id" : 1,
    "Name": "John Doe",
    "Occupation": "gardener"
}`)

我们有一个 JSON 对象,它被转换为字节。

err := json.Unmarshal(data, &u1)

我们使用 Unmarshal 将 JSON 解码到结构体中,形成 u1 结构体。

var u2 []User

我们声明一个 User 结构体切片。

data2 := []byte(`
[
    {"Id":2,"Name":"Roger Roe","Occupation":"driver"},
    {"Id":3,"Name":"Lucy Smith","Occupation":"teacher"},
    {"Id":4,"Name":"David Brown","Occupation":"programmer"}
]`)

这是一个要解码为 Go 切片的 JSON 数组。

err2 := json.Unmarshal(data2, &u2)

我们使用 Unmarshal 将 JSON 数组解码为 Go 切片。

for i := range u2 {

    fmt.Println(u2[i])
}

我们逐个打印解码后的 JSON 数组用户。

$ go run decoding.go 
Struct is: {1 John Doe gardener}
John Doe is a gardener.
{2 Roger Roe driver}
{3 Lucy Smith teacher}
{4 David Brown programmer}

Go JSON 美化打印

可以使用 MarshalIndent 函数美化打印输出。

pretty_print.go
package main

import (
    "encoding/json"
    "fmt"
    "log"
)

func main() {

    birds := map[string]interface{}{
        "sounds": map[string]string{
            "pigeon":  "coo",
            "eagle":   "squak",
            "owl":     "hoot",
            "duck":    "quack",
            "cuckoo":  "ku-ku",
            "raven":   "cruck-cruck",
            "chicken": "cluck",
            "rooster": "cock-a-doodle-do",
        },
    }

    data, err := json.MarshalIndent(birds, "", "    ")

    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(string(data))
}

在代码示例中,我们有一个鸟叫声的 map。输出使用 MarshalIndent 进行美化打印。

$ go run pretty_print.go 
{
    "sounds": {
        "chicken": "cluck",
        "cuckoo": "ku-ku",
        "duck": "quack",
        "eagle": "squak",
        "owl": "hoot",
        "pigeon": "coo",
        "raven": "cruck-cruck",
        "rooster": "cock-a-doodle-do"
    }
}

我们可以看到输出是缩进的,因此更易读。

Go 从文件读取 JSON

下一个示例从文件中读取 JSON 数据。

data.json
[
    {
        "name": "John Doe",
        "occupation": "gardener",
        "born": "1992-03-02"
    },
    {
        "name": "Brian Flemming",
        "occupation": "teacher",
        "born": "1967-11-22"
    },
    {
        "name": "Lucy Black",
        "occupation": "accountant",
        "born": "1995-04-07"
    },
    {
        "name": "John Doe",
        "occupation": "gardener",
        "born": "1972-08-30"
    }
]

这是 data.json 文件。

read_file.go
package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "log"
    "os"
)

type User struct {
    Name       string
    Occupation string
    Born       string
}

func main() {

    filename, err := os.Open("data.json")
    if err != nil {
        log.Fatal(err)
    }

    defer filename.Close()

    data, err := ioutil.ReadAll(filename)

    if err != nil {
        log.Fatal(err)
    }

    var result []User

    jsonErr := json.Unmarshal(data, &result)

    if jsonErr != nil {
        log.Fatal(jsonErr)
    }

    fmt.Println(result)
}

该示例从文件中读取 JSON 数据并将其解码为 user 结构体切片。

$ go run read_json.go 
[{John Doe gardener 1992-03-02} {Brian Flemming teacher 1967-11-22} 
 {Lucy Black accountant 1995-04-07} {John Doe gardener 1972-08-30}]

Go JSON HttpClient

net/http 包提供了 HTTP 客户端和服务器实现。

astros.go
package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
    "time"
)

type Astronaut struct {
    Name  string
    Craft string
}

type people struct {
    Number  int
    People  []Astronaut
    Message string
}

func main() {

    url := "http://api.open-notify.org/astros.json"

    var netClient = http.Client{
        Timeout: time.Second * 10,
    }

    res, err := netClient.Get(url)

    if err != nil {
        log.Fatal(err)
    }

    defer res.Body.Close()

    body, err := ioutil.ReadAll(res.Body)

    fmt.Println(body)

    if err != nil {
        log.Fatal(err)
    }

    astros := people{}

    jsonErr := json.Unmarshal(body, &astros)

    if jsonErr != nil {
        log.Fatal(jsonErr)
    }

    fmt.Println(astros)
}

该示例使用内置的 Go HTTP 客户端从 Web 服务读取数据。我们向一个服务发出 GET 请求,该服务返回国际空间站宇航员的数据。

$ go run astros.go 
{3 [{Chris Cassidy ISS} {Anatoly Ivanishin ISS} {Ivan Vagner ISS}] success}

此时,空间站上有三名宇航员。

来源

Go encoding/json 包 - 参考

在本文中,我们研究了 Golang 中的 JSON。

作者

我叫 Jan Bodnar,我是一名充满热情的程序员,拥有丰富的编程经验。我自 2007 年以来一直在撰写编程文章。迄今为止,我已撰写了 1,400 多篇文章和 8 本电子书。我在编程教学方面拥有十多年的经验。

列出所有 Go 教程