👨‍💻 簡介

今天的encoding/json package是我日常在開發web時很常用到的package之一,主要是用來將Go struct和 JSON 之間進行轉換。主要功能為資料序列化(marshalling)和反序列化(unmarshalling)。

主要功能

encoding/json package 主要用來將 Go struct轉換為 JSON 格式(marshalling)以及將 JSON 資料轉換為 Go struct(unmarshalling)。以下是一些主要功能:

將 Go struct轉換為 JSON

使用 json.Marshal 函數可以將 Go struct轉換為 JSON 格式的資料。

package main

import (
	"encoding/json"
	"fmt"
)

type Person struct {
	Name  string `json:"name"`
	Age   int    `json:"age"`
}

func main() {
	person := Person{Name: "Alan", Age: 25}
	jsonData, err := json.Marshal(person)
	if err != nil {
		fmt.Println("JSON 編碼失敗:", err)
		return
	}

	fmt.Println(string(jsonData))
	// 輸出: {"name":"Alan","age":25}
}

在上面的範例中,我們先定義了一個 Person struct,然後使用 json.Marshal 函數將 Person 轉換為 JSON 資料。

將 JSON 資料轉換為 Go struct

使用 json.Unmarshal 函數可以將 JSON 資料轉換為 Go struct。

package main

import (
	"encoding/json"
	"fmt"
)

type Person struct {
	Name string `json:"name"`
	Age  int    `json:"age"`
}

func main() {
	jsonData := []byte(`{"name":"Bob","age":30}`)
	var person Person

	err := json.Unmarshal(jsonData, &person)
	if err != nil {
		fmt.Println("JSON 解碼失敗:", err)
		return
	}

	fmt.Println("姓名:", person.Name)
	fmt.Println("年齡:", person.Age)
	// 輸出:
	// 姓名: Bob
	// 年齡: 30
}

反轉則是使用 json.Unmarshal 函數將 JSON 資料轉換為 Person 的struct。

自定義 JSON 鍵名

當需要API顯示自定義 JSON 欄位鍵名時,可以在 Go struct的欄位上使用 json 標籤來自定義 JSON 鍵名,方便與外部 API 或其他系統的格式相同。

package main

import (
	"encoding/json"
	"fmt"
)

type Person struct {
	FullName string `json:"full_name"`
	Age      int    `json:"age"`
}

func main() {
	person := Person{FullName: "Charlie Brown", Age: 10}
	jsonData, err := json.Marshal(person)
	if err != nil {
		fmt.Println("JSON 編碼失敗:", err)
		return
	}

	fmt.Println(string(jsonData))
	// 輸出: {"full_name":"Charlie Brown","age":10}
}

在這個範例中,我們使用 json 標籤來指定 FullName 欄位在 JSON 中的名稱為 “full_name”。

常見用法

解析複雜的 JSON 資料

encoding/json package 可以處理複雜的 JSON 資料,包括嵌套struct和陣列。

package main

import (
	"encoding/json"
	"fmt"
)

type Address struct {
	City    string `json:"city"`
	Country string `json:"country"`
}

type Person struct {
	Name    string  `json:"name"`
	Age     int     `json:"age"`
	Address Address `json:"address"`
}

func main() {
	jsonData := []byte(`{
		"name": "Alan",
		"age": 25,
		"address": {
			"city": "Taichung",
			"country": "Taiwan"
		}
	}`)

	var person Person

	err := json.Unmarshal(jsonData, &person)
	if err != nil {
		fmt.Println("JSON 解碼失敗:", err)
		return
	}

	fmt.Println("姓名:", person.Name)
	fmt.Println("年齡:", person.Age)
	fmt.Println("地址:", person.Address.Countryperson.Address.City )
	// 輸出:
	// 姓名: Alan
	// 年齡: 25
	// 地址: Taiwan Taichung
}

在這個範例中,我們定義了 AddressPerson 兩個struct,其中 Person 包含一個嵌套的 Address struct。我們使用 json.Unmarshal 函數解析嵌套struct的 JSON 資料。

處理 JSON 陣列

encoding/json package 也能夠處理 JSON 陣列。

package main

import (
	"encoding/json"
	"fmt"
)

type Item struct {
	ID   int    `json:"id"`
	Name string `json:"name"`
}

func main() {
	jsonData := []byte(`[
		{"id": 1, "name": "Item 1"},
		{"id": 2, "name": "Item 2"},
		{"id": 3, "name": "Item 3"}
	]`)

	var items []Item

	err := json.Unmarshal(jsonData, &items)
	if err != nil {
		fmt.Println("JSON 解碼失敗:", err)
		return
	}

	for _, item := range items {
		fmt.Printf("ID: %d, 名稱: %s\n", item.ID, item.Name)
	}
	// 輸出:
	// ID: 1, 名稱: Item 1
	// ID: 2, 名稱: Item 2
	// ID: 3, 名稱: Item 3
}

可以看到,我們定義了 Item struct,然後使用 json.Unmarshal 函數解析包含 JSON 陣列的 JSON 資料。

📚 參考資料