golang,go,博客,开源,编程
Go 中的 json.Marshal
和 json.Unmarshal
是 JSON 编解码的核心工具,底层原理主要依赖于 Go 的 反射机制(reflection)。这两个函数允许 Go 类型(如结构体、数组、切片、映射等)与 JSON 格式之间进行相互转换。具体来说,它们通过反射操作来访问对象的字段,生成 JSON 格式的字符串或从 JSON 字符串中恢复出 Go 对象。
json.Marshal
的原理json.Marshal
将一个 Go 数据结构转换为 JSON 格式的字节切片([]byte
)。它会对输入的 Go 对象进行递归地遍历,并根据字段类型的结构和标签将其转换成 JSON 格式。
string
、int
、float
等)会直接转换为对应的 JSON 类型。json.Marshal
,并将结果嵌套到外层 JSON 中。json
标签控制序列化:通过结构体标签(例如 json:"name"
)指定字段的名称或序列化行为。package main
import (
"encoding/json"
"fmt"
)
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
}
func main() {
p := Person{Name: "Alice", Age: 25}
// Marshal 将 Go 对象转换为 JSON 字符串
data, err := json.Marshal(p)
if err != nil {
fmt.Println("Error marshaling:", err)
return
}
fmt.Println(string(data)) // {"name":"Alice","age":25}
}
json.Marshal(p)
会使用反射机制遍历结构体 Person
,然后将 Name
和 Age
字段转换为 JSON 对象。{"name":"Alice","age":25}
。json.Unmarshal
的原理json.Unmarshal
用于将 JSON 字符串解析并填充到 Go 对象中。它会通过反射将 JSON 数据与 Go 结构体、数组、切片或映射进行匹配。
json.Unmarshal
会读取目标对象(如结构体、切片等)的类型,并根据其类型初始化合适的内存空间。json:"name"
)来指定映射关系。string
、int
)将 JSON 数据类型转换为对应的 Go 类型,并将值填充到目标字段中。
Unmarshal
会返回错误。Unmarshal
会为其分配内存并赋值。Unmarshal
会递归地解码这些结构体字段。package main
import (
"encoding/json"
"fmt"
)
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
}
func main() {
data := []byte(`{"name":"Bob","age":30}`)
var p Person
// Unmarshal 将 JSON 字符串解析为 Go 对象
err := json.Unmarshal(data, &p)
if err != nil {
fmt.Println("Error unmarshaling:", err)
return
}
fmt.Println(p) // {Bob 30}
}
json.Unmarshal(data, &p)
会根据 JSON 数据 {"name":"Bob","age":30}
中的字段,将其值解析并填充到 p
结构体的 Name
和 Age
字段中。Person
中的字段是导出的并且有对应的 json
标签,Unmarshal
能正确地将 name
和 age
字段从 JSON 中提取出来并赋值。Go 的 json
包在 Marshal
和 Unmarshal
操作中广泛使用了反射机制。反射使得 Go 在运行时能够动态地获取对象的类型、字段和方法等信息。这也是 Go 在没有传统的类继承和接口时依然能够进行强大的序列化和反序列化的原因。
reflect.Value.FieldByName
可以用来通过字段名称访问结构体字段。reflect.Value.Set
可以设置结构体字段的值。json:"name"
)通过反射解析并在 Marshal
和 Unmarshal
过程中使用。json:"name"
)Go 结构体中的字段标签(如 json:"name"
)用于控制 JSON 编解码的行为。常见的标签包括:
json:"name"
表示将 JSON 中的 name
字段映射到 Go 结构体中的 Name
字段。json:"-"
可以忽略某个字段。json:",omitempty"
可以在字段值为空时省略该字段。例如:
type Person struct {
Name string `json:"name"`
Age int `json:"age,omitempty"`
}
在上述例子中,如果 Age
字段为 0
(零值),它将不会被序列化为 JSON 字符串。
json.Marshal
和 json.Unmarshal
使用了 反射 机制来处理 Go 对象与 JSON 格式之间的转换。json.Marshal
通过反射遍历结构体字段,生成符合 JSON 格式的字节数组。json.Unmarshal
通过反射解析 JSON 数据,并将其填充到 Go 对象中。这两个函数为 Go 提供了强大的 JSON 编解码功能,并且通过反射机制使得 Go 语言即使没有传统的类和继承机制,也能轻松处理复杂的序列化和反序列化任务。