答案:Golang中处理JSON数据的核心是encoding/json包,通过json.Marshal和json.Unmarshal实现序列化与反序列化,利用结构体标签如json:"name"、omitempty、string等控制字段映射与输出,结合反射机制在运行时解析标签,实现灵活的JSON转换;对于缺失字段可采用指针或自定义UnmarshalJSON处理,类型不匹配可通过string标签或interface{}应对,序列化优化包括omitempty减少冗余、自定义MarshalJSON控制输出格式,以及使用json.Encoder进行流式写入以提升性能。

在Golang里处理JSON数据,核心就是用标准库的
encoding/json
在Golang中处理JSON,主要围绕
json.Unmarshal
json.Marshal
JSON解析(Unmarshal)
当你拿到一段JSON格式的字节数据,想把它变成Go语言里能操作的对象时,
json.Unmarshal
立即学习“go语言免费学习笔记(深入)”;
package main
import (
"encoding/json"
"fmt"
"time"
)
type User struct {
ID int `json:"id"`
Name string `json:"user_name"`
Email string `json:"email,omitempty"` // omitempty在序列化时有用,反序列化时忽略
CreatedAt time.Time `json:"created_at"`
IsActive bool `json:"is_active,string"` // 期望JSON中布尔值是字符串"true"或"false"
Profile *Profile `json:"profile"` // 指针类型,如果JSON中没有这个字段,会是nil
}
type Profile struct {
Bio string `json:"bio"`
Age int `json:"age"`
}
func main() {
jsonData := []byte(`{
"id": 101,
"user_name": "张三",
"email": "zhangsan@example.com",
"created_at": "2023-10-26T10:00:00Z",
"is_active": "true",
"profile": {
"bio": "一个普通的Go开发者",
"age": 30
}
}`)
var user User
err := json.Unmarshal(jsonData, &user)
if err != nil {
fmt.Println("解析JSON失败:", err)
return
}
fmt.Printf("解析后的用户数据: %+v\n", user)
fmt.Printf("用户ID: %d, 姓名: %s, 邮箱: %s, 创建时间: %s, 活跃状态: %t\n",
user.ID, user.Name, user.Email, user.CreatedAt.Format(time.RFC3339), user.IsActive)
if user.Profile != nil {
fmt.Printf("用户简介: %s, 年龄: %d\n", user.Profile.Bio, user.Profile.Age)
}
// 尝试一个缺少字段和类型不匹配的例子
invalidJsonData := []byte(`{
"id": "abc",
"user_name": "李四"
}`)
var user2 User
err = json.Unmarshal(invalidJsonData, &user2)
if err != nil {
fmt.Println("\n解析无效JSON失败 (预期错误):", err) // 期望这里会报错
}
}这里我们定义了一个
User
json:"..."
encoding/json
json:"user_name"
user_name
Name
JSON序列化(Marshal)
反过来,如果你想把Go结构体里的数据转换成JSON格式的字节数据,然后可能存到文件里,或者通过网络发送出去,那就要用到
json.Marshal
package main
import (
"encoding/json"
"fmt"
"time"
)
type Product struct {
Name string `json:"product_name"`
Price float64 `json:"price"`
InStock bool `json:"in_stock,omitempty"` // 如果为零值(false),则不输出
SKU string `json:"-"` // 忽略此字段
CreatedAt time.Time `json:"created_at,string"` // 序列化为字符串
}
func main() {
p := Product{
Name: "Go语言编程",
Price: 99.50,
InStock: true,
SKU: "GO-BOOK-001",
CreatedAt: time.Now(),
}
jsonData, err := json.Marshal(p)
if err != nil {
fmt.Println("序列化失败:", err)
return
}
fmt.Printf("\n序列化后的产品数据: %s\n", jsonData)
// 演示omitempty效果
p2 := Product{
Name: "Python编程",
Price: 88.00,
InStock: false, // omitempty会使此字段不输出
SKU: "PY-BOOK-001",
CreatedAt: time.Now(),
}
jsonData2, err := json.Marshal(p2)
if err != nil {
fmt.Println("序列化失败:", err)
return
}
fmt.Printf("序列化后的产品数据 (InStock为false): %s\n", jsonData2)
// 美化输出
jsonDataPretty, err := json.MarshalIndent(p, "", " ")
if err != nil {
fmt.Println("美化序列化失败:", err)
return
}
fmt.Printf("\n美化序列化后的产品数据:\n%s\n", jsonDataPretty)
}这里
json:"-"
SKU
omitempty
false
""
0
nil
string
Go语言的
struct tag
encoding/json
最常见的JSON标签格式是
json:"name,option1,option2..."
字段名称映射 (json:"name"
encoding/json
snake_case
CamelCase
json:"user_name"
user_name
UserName
encoding/json
UserName
忽略字段 (json:"-"
json:"-"
空值省略 (json:",omitempty"
int
0
string
""
bool
false
nil
nil
omitempty
encoding/json
json:"email,omitempty"
"email": ""
字符串化 (json:",string"
json:"age,string"
age
"30"
int
age
30
"age": "30"
解析原理:反射(Reflection)
encoding/json
json.Marshal
json.Unmarshal
reflect.TypeOf
reflect.StructField.Tag.Get("json")json
json:"..."
omitempty
string
-
encoding/json
这个过程都是在运行时动态进行的,不需要你在编译时写死映射关系,所以非常灵活和强大。
处理JSON数据时,面对缺失字段和类型不匹配是家常便饭,这往往是数据源不可控或者版本迭代造成的。Go的
encoding/json
处理缺失字段:
零值填充(默认行为): 如果JSON数据中缺少某个字段,而你的Go结构体中定义了该字段,
json.Unmarshal
int
float64
0
string
""
bool
false
slice
map
interface{}nil
struct
使用指针类型(推荐): 对于那些在JSON中可能存在也可能不存在的字段,我个人非常推荐使用指针类型。 例如:
Email *string
。 如果JSON中没有
这个字段,那么
会是
。你可以通过检查
来判断这个字段是否存在。这比零值更有语义,因为
明确表示“不存在”或“未提供”,而空字符串
或
自定义UnmarshalJSON
json.Unmarshaler
UnmarshalJSON([]byte) error
type MyData struct {
Value1 string `json:"value1"`
Value2 int `json:"value2"`
}
// 自定义 UnmarshalJSON
func (d *MyData) UnmarshalJSON(data []byte) error {
// 定义一个匿名结构体,用于避免递归调用
type Alias MyData
aux := &struct {
Value2 *int `json:"value2"` // 使用指针来区分0和缺失
*Alias
}{
Alias: (*Alias)(d),
}
if err := json.Unmarshal(data, aux); err != nil {
return err
}
// 如果Value2缺失,给一个默认值
if aux.Value2 == nil {
d.Value2 = 999 // 默认值
} else {
d.Value2 = *aux.Value2
}
return nil
}处理类型不匹配:
json.Unmarshal
json.Unmarshal
"age": "thirty"
Age int
使用json:",string"
Age int
可以将
解析为
使用interface{}json.RawMessage
interface{}json.RawMessage
Unmarshal
type FlexibleData struct {
ID int `json:"id"`
Data json.RawMessage `json:"data"` // 延迟解析
}
jsonStr := `{"id": 1, "data": {"key": "value", "num": 123}}`
var flexData FlexibleData
json.Unmarshal([]byte(jsonStr), &flexData)
var specificData map[string]interface{}
json.Unmarshal(flexData.Data, &specificData) // 再次解析Data字段
fmt.Printf("Parsed specific data: %+v\n", specificData)自定义UnmarshalJSON
time.Time
UnmarshalJSON
比如,如果一个字段可能是一个字符串,也可能是一个数字,你可以在
UnmarshalJSON
处理这些情况的关键在于,你需要对你的数据源有清晰的认识,然后选择最适合的Go类型和解析策略。有时候,过于宽松的解析可能会掩盖数据问题,而过于严格又可能导致不必要的解析失败。找到那个平衡点,才是最重要的。
在Golang中进行JSON序列化,除了基本的
json.Marshal
利用omitempty
,omitempty
Email string
。如果用户没有提供邮箱,那么
字段是空字符串
,序列化时就不会出现
自定义MarshalJSON
json.Marshaler
MarshalJSON() ([]byte, error)
encoding/json
time.Time
package main
import (
"encoding/json"
"fmt"
"time"
)
type Event struct {
Name string
Timestamp time.Time
// 其他字段...
}
// 为Event实现MarshalJSON方法
func (e Event) MarshalJSON() ([]byte, error) {
// 创建一个匿名结构体,用于避免递归调用(非常重要!)
// 这里我们将Timestamp序列化为Unix毫秒时间戳
type Alias Event // Alias是Event的别名,拥有相同的字段但没有自定义方法
return json.Marshal(&struct {
Alias
UnixMilli int64 `json:"timestamp_ms"` // 新增一个字段用于输出
}{
Alias: (Alias)(e),
UnixMilli: e.Timestamp.UnixMilli(),
})
}
func main() {
event := Event{
Name: "会议开始",
Timestamp: time.Now(),
}
jsonData, _ := json.Marshal(event)
fmt.Printf("自定义序列化后的事件: %s\n", jsonData)
}在这个例子中,
Timestamp
timestamp_ms
使用json.Encoder
http.ResponseWriter
io.Writer
以上就是怎样用Golang处理JSON数据 解析struct标签与序列化技巧的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号