答案是使用Go的encoding/json库通过json.Marshal和json.Unmarshal实现序列化与反序列化,利用结构体标签控制字段映射,omitempty忽略零值字段,优先使用具体结构体而非interface{}以提升性能,并通过检查错误类型实现健壮的错误处理。

Go语言的
encoding/json
要使用Go的
encoding/json
json.Marshal
json.Unmarshal
序列化(Go -> JSON):
当你有一个Go结构体或任何可序列化的Go值,想把它变成JSON字符串时,
json.Marshal
[]byte
立即学习“go语言免费学习笔记(深入)”;
package main
import (
"encoding/json"
"fmt"
"log"
)
type User struct {
ID int `json:"id"`
Name string `json:"name"`
Email string `json:"email,omitempty"` // omitempty表示如果Email为空字符串,则不包含此字段
Age int `json:"-"` // "-"表示忽略此字段
CreatedAt string `json:"created_at"` // 字段名转换为snake_case
}
func main() {
user := User{
ID: 1,
Name: "张三",
// Email: "zhangsan@example.com", // 如果不设置,omitempty会生效
Age: 30, // 这个字段会被忽略
CreatedAt: "2023-10-26T10:00:00Z",
}
jsonData, err := json.Marshal(user)
if err != nil {
log.Fatalf("序列化失败: %v", err)
}
fmt.Printf("序列化结果: %s\n", jsonData)
// 如果想格式化输出,可以用MarshalIndent
jsonDataIndent, err := json.MarshalIndent(user, "", " ")
if err != nil {
log.Fatalf("格式化序列化失败: %v", err)
}
fmt.Printf("格式化序列化结果:\n%s\n", jsonDataIndent)
}反序列化(JSON -> Go):
反过来,当你从文件、网络请求等地方拿到一个JSON字符串(或字节切片),想把它还原成Go结构体时,
json.Unmarshal
package main
import (
"encoding/json"
"fmt"
"log"
)
type Product struct {
SKU string `json:"sku"`
Name string `json:"product_name"`
Price float64 `json:"price"`
InStock bool `json:"in_stock"`
Tags []string `json:"tags,omitempty"`
}
func main() {
jsonString := `{
"sku": "PROD001",
"product_name": "Go语言编程指南",
"price": 99.99,
"in_stock": true,
"tags": ["编程", "Go", "技术"]
}`
var product Product
err := json.Unmarshal([]byte(jsonString), &product)
if err != nil {
log.Fatalf("反序列化失败: %v", err)
}
fmt.Printf("反序列化结果: %+v\n", product)
// 尝试反序列化一个缺少字段的JSON
jsonStringMissing := `{
"sku": "PROD002",
"product_name": "简化版书籍",
"price": 49.50
}`
var productMissing Product
err = json.Unmarshal([]byte(jsonStringMissing), &productMissing)
if err != nil {
log.Fatalf("反序列化缺少字段失败: %v", err)
}
fmt.Printf("反序列化缺少字段结果: %+v\n", productMissing) // InStock会是false,Tags会是nil
}这块是
encoding/json
json.Marshal
至于命名约定,外部系统往往倾向于使用
snake_case
user_name
camelCase
userName
encoding/json
struct tags
json:"your_json_field_name"
比如:
type Order struct {
OrderID string `json:"order_id"` // 自定义JSON字段名为order_id
TotalPrice float64 `json:"total_price"` // 自定义JSON字段名为total_price
Status string `json:"status,omitempty"` // 如果Status为空字符串,则忽略该字段
internalID string // 小写字母开头,会被忽略
}这里
omitempty
omitempty
json.Marshal
0
false
omitempty
还有一个不常用但偶尔能救命的标签是
json:",string"
int
time.Time
MarshalJSON
UnmarshalJSON
本文档主要讲述的是JSON.NET 简单的使用;JSON.NET使用来将.NET中的对象转换为JSON字符串(序列化),或者将JSON字符串转换为.NET中已有类型的对象(反序列化?)。希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来看看
0
反序列化,也就是
json.Unmarshal
首先,对于JSON中存在但Go结构体中没有对应字段的键值对,json.Unmarshal
map[string]interface{}类型不匹配是另一个常见的坑。如果JSON中的字段类型与Go结构体中定义的类型不一致,
json.Unmarshal
*json.UnmarshalTypeError
"age": "30"
Age int
type Person struct {
Name string `json:"name"`
Age int `json:"age"` // 期望是数字
}
func main() {
jsonBadAge := `{"name": "Alice", "age": "thirty"}` // age是字符串
var p Person
err := json.Unmarshal([]byte(jsonBadAge), &p)
if err != nil {
fmt.Printf("反序列化错误: %v\n", err) // 会报错:json: cannot unmarshal string into Go struct field Person.age of type int
}
}解决这类问题,除了确保JSON数据源的正确性外,你还可以:
interface{}map[string]interface{}[]interface{}UnmarshalJSON
json.Unmarshaler
json.RawMessage
json.RawMessage
Unmarshal
我个人觉得,在处理未知字段和类型不匹配时,最重要的是预设你的数据边界。如果数据源是你可控的,那就严格定义结构体,让
Unmarshal
map[string]interface{}UnmarshalJSON
处理JSON,尤其是在高并发或大数据量的场景下,性能和稳健的错误处理是绕不开的话题。
性能优化:
使用json.Encoder
json.Decoder
json.NewEncoder(writer)
json.NewDecoder(reader)
io.Writer
io.Reader
// 示例:使用Encoder写入JSON到HTTP响应
// func handler(w http.ResponseWriter, r *http.Request) {
// data := MyStruct{...}
// w.Header().Set("Content-Type", "application/json")
// if err := json.NewEncoder(w).Encode(data); err != nil {
// http.Error(w, err.Error(), http.StatusInternalServerError)
// return
// }
// }避免不必要的interface{}
interface{}interface{}重用json.Encoder
json.Decoder
sync.Pool
json.Encoder
json.Decoder
bufio.Writer
bufio.Reader
结构体字段顺序: 这更像是一个Go语言本身的优化,而非
encoding/json
错误处理:
错误处理在任何I/O操作中都至关重要,JSON编解码也不例外。
始终检查error
json.Marshal
json.Unmarshal
error
data, err := json.Marshal(myStruct)
if err != nil {
log.Printf("JSON序列化失败: %v", err)
// 根据业务需求处理错误,例如返回HTTP 500
return
}
err = json.Unmarshal(jsonData, &myStruct)
if err != nil {
log.Printf("JSON反序列化失败: %v", err)
// 根据业务需求处理错误,例如返回HTTP 400 Bad Request
return
}区分错误类型:
encoding/json
*json.UnmarshalTypeError
*json.InvalidUnmarshalError
Unmarshal
*json.SyntaxError
通过使用
errors.As
UnmarshalTypeError
var unmarshalTypeError *json.UnmarshalTypeError
if errors.As(err, &unmarshalTypeError) {
fmt.Printf("JSON类型不匹配错误:字段 '%s' 期望类型为 %s,但实际为 %s\n",
unmarshalTypeError.Field, unmarshalTypeError.Type, unmarshalTypeError.Value)
} else if err != nil {
fmt.Printf("其他JSON反序列化错误: %v\n", err)
}处理json.Decoder
io.EOF
json.NewDecoder
io.EOF
io.EOF
自定义MarshalJSON
UnmarshalJSON
我经常发现,很多初学者在处理JSON时,往往忽略了错误检查,或者只是简单地
log.Fatal
以上就是Golang encoding/json库JSON序列化与反序列化的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号