53、Go语言基础 - JSON 处理 - 解析与生成 JSON
hi,我是温新
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,通常用于数据的序列化和跨网络传输。它是一种文本格式,易于阅读和编写,同时也易于解析和生成
解析 JSON
Go 语言中,解析 JSON 有两种方式:一种是解析到结构体,另一种是解析到接口。
解析到结构体上,是在知晓被解析的 JSON 数据的结构前提采取的方案,如果不知道被解析的数据的格式,则应采用解析到接口的方案。
json.Unmarshal
函数用于将JSON数据解析为Go语言中的数据结构。
func Unmarshal(data []byte, v interface{}) error
-
data
:表示包含要解析的 JSON 数据的字节切片。 -
v
:表示要将 JSON 数据解析到的目标 Go 数据结构。这通常是一个指向结构体的指针。 - 返回值:如果解析成功,返回
nil
;如果解析时出现错误,返回描述错误的值。
解析到结构体
package main
import (
"encoding/json"
"fmt"
)
func main() {
// 示例 JSON 数据
jsonData := `{
"name": "王美丽",
"age": 19,
"address": {
"street": "光谷",
"city": "武汉"
}
}`
// 创建一个 Person 结构体变量
var person Person
// 使用 json.Unmarshal 解析 JSON 数据到结构体变量
err := json.Unmarshal([]byte(jsonData), &person)
if err != nil {
fmt.Println("解析 JSON 错误:", err)
return
}
// 访问解析后的数据
fmt.Println(person)
fmt.Println(person.Name)
fmt.Println(person.Address.City)
}
// 创建结构体来匹配嵌套 JSON 数据的结构
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
Address struct {
Street string `json:"street"`
City string `json:"city"`
} `json:"address"`
}
这个示例演示了如何使用嵌套结构体来解析具有复杂结构的嵌套 JSON 数据。通过嵌套结构体,我们可以轻松地访问嵌套的 JSON 对象字段,以获取所需的数据。这对于处理复杂的 JSON 数据非常有用。
解析到接口案例
package main
import (
"encoding/json"
"fmt"
)
func main() {
// 示例 JSON 数据
jsonData := `{
"name": "王美丽",
"age": 19
}`
// 创建一个 map 用于解析 JSON 数据
var data map[string]JSONData
// 使用 json.Unmarshal 解析 JSON 数据到 map 中
err := json.Unmarshal([]byte(jsonData), &data)
if err != nil {
fmt.Println("解析 JSON 错误:", err)
return
}
// 访问解析后的数据,包括嵌套结构
fmt.Println(data)
name, _ := data["name"].(string)
age, _ := data["age"].(float64)
fmt.Println(name, age)
}
// 定义一个接口类型,用于表示JSON数据的通用结构
type JSONData interface {
}
生成 JSON
json.Marshal
函数用于将 Go 数据结构编码为 JSON 格式的数据。
func Marshal(v interface{}) ([]byte, error)
-
v
:表示要编码为 JSON 格式的 Go 数据结构。通常,这是一个结构体、切片、映射或其他数据类型。 - 返回值:如果编码成功,返回包含 JSON 数据的字节切片(
[]byte
);如果编码时出现错误,返回描述错误的值。
案例一
package main
import (
"encoding/json"
"fmt"
)
func main() {
// 创建一个 User 结构体变量
user := User{
Name: "王美丽",
Age: 19,
}
// 使用 json.Marshal 将结构体编码为 JSON 数据
jsonData, err := json.Marshal(user)
if err != nil {
fmt.Println("编码为 JSON 错误:", err)
return
}
// 打印编码后的 JSON 数据
fmt.Println(string(jsonData))
}
type User struct {
Name string `json:"name"`
Age int `json:"age"`
}
输出结果
{"name":"王美丽","age":19}
这个示例演示了如何使用json.Marshal
函数将 Go 数据结构编码为 JSON 数据。 JSON 数据中的字段名称由结构体的字段和标签指定,以确保正确的映射。
代码解释:
- 我们首先定义了一个名为
User
的结构体,该结构体的字段与 JSON 数据的字段名称相匹配。使用json
标签来指定结构体字段与 JSON 字段之间的映射关系。 - 创建一个
User
结构体变量user
,我们将使用json.Marshal
将其编码为 JSON 数据。 - 使用
json.Marshal
函数将user
结构体编码为 JSON 数据。编码成功后,JSON 数据存储在jsonData
变量中,如果编码过程中出现错误,我们将捕获错误并打印错误消息。 - 最后,我们打印编码后的 JSON 数据。这个 JSON 数据表示
person
结构体的字段和值,它可以轻松地在应用程序中进行传输或存储。
案例二
package main
import (
"encoding/json"
"fmt"
)
func main() {
// 创建一个 Serverslice 结构体变量 s,用于存储多个 Server 结构体的切片
var s Serverslice
// 使用 append 函数将两个 Server 结构体添加到 s.Servers 切片中
s.Servers = append(s.Servers, Server{ServerName: "Linux1", ServerIp: "127.0.0.1:8999"})
s.Servers = append(s.Servers, Server{ServerName: "Linux2", ServerIp: "127.0.0.1:9999"})
// 使用 json.Marshal 将 Serverslice 结构体编码为 JSON 数据
b, err := json.Marshal(s)
if err != nil {
fmt.Println("json err:", err)
return
}
// 打印编码后的 JSON 数据
fmt.Println(string(b))
}
// 定义一个 Server 结构体,用于表示服务器的名称和IP地址
type Server struct {
ServerName string `json:"server_name"`
ServerIp string `json:"server_ip"`
}
// 定义一个 Serverslice 结构体,包含一个 Servers 切片,用于表示多个服务器的集合
type Serverslice struct {
Servers []Server `json:"servers"`
}
输出结果
{"servers":[{"server_name":"Linux1","server_ip":"127.0.0.1:8999"},{"server_name":"Linux2","server_ip":"127.0.0.1:9999"}]}
如果要输出小写,则必须为结构体打上 tag
。
// 首字母大写的输出
type Server struct {
ServerName string
ServerIp string
}
// 首字母写小输出
type Server struct {
ServerName string `json:"server_name"`
ServerIp string `json:"server_ip"`
}
生成 JSON 注意项
Marshal
函数只在转换成功时才会返回数据。在转换过程中需要注意如下几点:
- 1、JSON 对象只支持 string 作为 key, 所以要编码一个 map,必须是 map[string]T 这种类型(T 为 Go 中的任意类型);
- 2、channel、complex、function 不能被编码成 JSON;
- 3、嵌套的数据是不能编码的,否则 JSON 编码会陷入死循环;
- 4、指针在编码时会输出指针指向的内容,而空指针会输出 null。
请登录后再评论