Go的JSON转化

在Go语言中,处理JSON(JavaScript Object Notation)数据非常常见,特别是在与Web服务交互时。Go提供了内置的encoding/json包来支持JSON的序列化(将Go对象转换为JSON格式)和反序列化(将JSON格式的数据解析为Go对象)。

1. JSON的序列化和反序列化

1.1 序列化(结构体转换为JSON)

将Go结构体转换为JSON格式使用json.Marshal函数。

go 复制代码
package main

import (
	"encoding/json"
	"fmt"
)

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

func main() {
	// 初始化结构体
	p := Person{Name: "Alice", Age: 30}

	// 将结构体转换为JSON
	jsonData, err := json.Marshal(p)
	if err != nil {
		fmt.Println("Error marshaling JSON:", err)
		return
	}

	// 输出JSON数据
	fmt.Println(string(jsonData)) // {"name":"Alice","age":30}
}
1.2 反序列化(JSON转换为结构体)

将JSON数据转换为Go结构体使用json.Unmarshal函数。

go 复制代码
package main

import (
	"encoding/json"
	"fmt"
)

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

func main() {
	// JSON数据
	jsonData := `{"name": "Bob", "age": 25}`

	// 反序列化JSON到结构体
	var p Person
	err := json.Unmarshal([]byte(jsonData), &p)
	if err != nil {
		fmt.Println("Error unmarshaling JSON:", err)
		return
	}

	// 输出结构体
	fmt.Println(p) // {Bob 25}
}

2. 处理map类型的JSON

JSON对象可以表示为Go的map类型,其中键是字符串,值可以是任意类型。对于动态的或不确定结构的数据,使用map[string]interface{}

2.1 将map转换为JSON
go 复制代码
package main

import (
	"encoding/json"
	"fmt"
)

func main() {
	// 使用map表示JSON数据
	data := map[string]interface{}{
		"name": "Charlie",
		"age":  28,
		"hobbies": []string{"Reading", "Cycling"},
	}

	// 将map转换为JSON
	jsonData, err := json.Marshal(data)
	if err != nil {
		fmt.Println("Error marshaling JSON:", err)
		return
	}

	// 输出JSON数据
	fmt.Println(string(jsonData))
}
2.2 将JSON转换为map
go 复制代码
package main

import (
	"encoding/json"
	"fmt"
)

func main() {
	// JSON数据
	jsonData := `{"name": "Diana", "age": 35, "hobbies": ["Music", "Traveling"]}`

	// 创建一个空的map
	var data map[string]interface{}

	// 将JSON数据反序列化到map
	err := json.Unmarshal([]byte(jsonData), &data)
	if err != nil {
		fmt.Println("Error unmarshaling JSON:", err)
		return
	}

	// 输出map数据
	fmt.Println(data) // map[age:35 hobbies:[Music Traveling] name:Diana]
}

3. JSON标签(struct tags)

Go语言中的结构体字段可以使用标签(tags)来指定JSON中的字段名。常见的用法是为结构体字段添加json标签,以定义序列化时的字段名。

3.1 设置字段名
go 复制代码
package main

import (
	"encoding/json"
	"fmt"
)

type Person struct {
	Name    string `json:"name"`
	Age     int    `json:"age"`
	Address string `json:"address,omitempty"` // omitempty表示如果字段值为空则不序列化
}

func main() {
	p := Person{Name: "Eva", Age: 30}

	// 将结构体转为JSON
	jsonData, err := json.Marshal(p)
	if err != nil {
		fmt.Println("Error marshaling JSON:", err)
		return
	}

	fmt.Println(string(jsonData)) // {"name":"Eva","age":30}
}
3.2 使用omitempty标签

omitempty标签使得字段在为空时不进行JSON序列化。对于指针类型、字符串、数组、切片和数字类型,当其值为零值时,omitempty会忽略该字段。

go 复制代码
package main

import (
	"encoding/json"
	"fmt"
)

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

func main() {
	p := Person{Name: "Grace", Age: 25}

	// 序列化为JSON
	jsonData, err := json.Marshal(p)
	if err != nil {
		fmt.Println("Error marshaling JSON:", err)
		return
	}

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

4. 格式化输出(美化JSON)

可以使用json.MarshalIndent将JSON格式化输出,使其更易读(带有缩进)。

go 复制代码
package main

import (
	"encoding/json"
	"fmt"
)

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

func main() {
	p := Person{Name: "Hannah", Age: 28, Address: "London"}

	// 美化输出
	jsonData, err := json.MarshalIndent(p, "", "    ")
	if err != nil {
		fmt.Println("Error marshaling JSON:", err)
		return
	}

	fmt.Println(string(jsonData))
}

输出:

json 复制代码
{
    "name": "Hannah",
    "age": 28,
    "address": "London"
}

5. 处理JSON中的空值和类型不匹配

Go中的interface{}类型允许在JSON反序列化时处理不同类型的数据。需要小心处理类型不匹配的情况。

5.1 空字段的处理

对于空值或没有定义的字段,在反序列化时可以忽略,或者通过结构体标签设置为零值。

5.2 类型断言

如果反序列化后的数据类型是interface{},你需要使用类型断言来访问具体类型的值。

go 复制代码
package main

import (
	"encoding/json"
	"fmt"
)

func main() {
	// JSON数据
	jsonData := `{"name": "Ivy", "age": 33, "active": true}`

	var data map[string]interface{}
	err := json.Unmarshal([]byte(jsonData), &data)
	if err != nil {
		fmt.Println("Error unmarshaling JSON:", err)
		return
	}

	// 使用类型断言
	if age, ok := data["age"].(float64); ok {
		fmt.Println("Age:", age)
	} else {
		fmt.Println("Age is missing or not a number")
	}

	// 直接访问布尔类型
	if active, ok := data["active"].(bool); ok {
		fmt.Println("Active:", active)
	}
}

6. 将JSON字符串映射到数组或切片

Go支持将JSON数据映射到数组或切片中,适用于处理JSON数组。

示例:JSON数组到Go切片
go 复制代码
package main

import (
	"encoding/json"
	"fmt"
)

func main() {
	// JSON数组
	jsonData := `[
		{"name": "Jack", "age": 25},
		{"name": "Tom", "age": 28},
		{"name": "Alice", "age": 30}
	]`

	// 创建切片并解析JSON数据
	var people []map[string]interface{}
	err := json.Unmarshal([]byte(jsonData), &people)
	if err != nil {
		fmt.Println("Error unmarshaling JSON:", err)
		return
	}

	// 输出数据
	for _, person := range people {
		fmt.Println(person)
	}
}
  • 序列化 :使用json.Marshal将Go对象转换为JSON。
  • 反序列化 :使用json.Unmarshal将JSON数据解析为Go对象。
  • 标签 :可以使用json标签指定字段名,并使用omitempty控制字段是否为空时不序列化。
  • 格式化 :使用json.MarshalIndent生成格式化输出。
  • 空值和类型断言 :通过interface{}和类型断言处理复杂的JSON数据。
  • 切片和数组:支持将JSON数组解析为Go切片。
相关推荐
kevin_tech14 分钟前
Go API 多种响应的规范化处理和简化策略
开发语言·后端·golang·状态模式
幺零九零零3 小时前
【Golang】sql.Null* 类型使用(处理空值和零值)
数据库·sql·golang
cookies_s_s4 小时前
Golang--DOS命令、变量、基本数据类型、标识符
golang
__AtYou__4 小时前
Golang | Leetcode Golang题解之第541题反转字符串II
leetcode·golang·题解
幺零九零零12 小时前
【Golang】validator库的使用
开发语言·后端·golang
海绵宝宝de派小星13 小时前
Go:接口和反射
开发语言·后端·golang
techdashen14 小时前
Go Modules和 雅典项目
开发语言·后端·golang
flying robot14 小时前
Go的数组,slice切片,map的使用
笔记·golang
=(^.^)=哈哈哈14 小时前
从安全角度看多线程(附Golang举例)
爬虫·python·golang