上次我們介紹了 Go 語言中序列化和反序列化 JSON 數據的兩個方法 Marshal() 和 Unmarshal(),並以示例演示了它們的用法。
我們在例子中看到,需要事先聲明好對應的結構體,才能跟 JSON 字段映射起來。
有的時候,如果 JSON 數據的定義過於復雜,我們需要一種更加靈活的方式來處理。在這種情況下,可以將 JSON 數據映射到一個 map 結構中。
下面我們就來演示一下這種方式:
// 使用map結構 將JSON字符串轉為對象
package main
import (
"encoding/json"
"fmt"
)
var JSON = `{
"group": "programmer",
"persons": [
{
"name": "Jack",
"age": 25
},
{
"name": "Lily",
"age": 20
}
]
}`
func main() {
var bytes []byte
var data map[string]interface{}
// 先將字符串轉為字節切片
bytes = []byte(JSON)
// 將字節切片映射到map上
json.Unmarshal(bytes, &data)
fmt.Println("group:", data["group"])
// 轉為[]interface{}類型
persons := data["persons"].([]interface{})
for index, item := range persons {
// 類型轉換
person := item.(map[string]interface{})
age := person["age"]
// 更改年齡
person["age"] = age.(float64) + 1
// 打印最新個人信息
fmt.Println("person", index, ":", person["name"].(string), age, "->", person["age"].(float64))
}
// 序列化為JSON字符串
newBytes, _ := json.MarshalIndent(&data, "", " ");
// 打印新的JSON數據
fmt.Println(string(newBytes))
}
在上面代碼中,我們先定義了一個 map 變量,其 key 是 string 類型,value 是 interface{} 通用類型,這樣可以兼容多種數據類型,在取值的時候進行一次類型轉換即可。
之后我們調用 json.Unmarshal() 方法來將 JSON 字符串轉為對象,這個我們前面也介紹過。
在轉換完之后,取字段的時候我們應該以 map 的方式來執行,在取 persons 字段時,我們使用了下面這種方式:
// 轉為[]interface{}類型
persons := data["persons"].([]interface{})
必選先轉換為 []interface{} 類型,才能執行后續的 range 操作。在 range 內部,同樣需要對當前遍歷的對象做類型轉換,才能安全地讀寫對象的數據。
最后,運行上面的程序,控制台打印內容如下:
group: programmer
person 0 : Jack 25 -> 26
person 1 : Lily 20 -> 21
{
"group": "programmer",
"persons": [
{
"age": 26,
"name": "Jack"
},
{
"age": 21,
"name": "Lily"
}
]
}
