53、Go语言基础 - JSON 处理 - 解析与生成 JSON

作者: 温新

分类: 【Go基础】

阅读: 362

时间: 2023-12-05 00:44:44

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 数据中的字段名称由结构体的字段和标签指定,以确保正确的映射。

代码解释:

  1. 我们首先定义了一个名为User的结构体,该结构体的字段与 JSON 数据的字段名称相匹配。使用json标签来指定结构体字段与 JSON 字段之间的映射关系。
  2. 创建一个User结构体变量user,我们将使用json.Marshal将其编码为 JSON 数据。
  3. 使用json.Marshal函数将user结构体编码为 JSON 数据。编码成功后,JSON 数据存储在jsonData变量中,如果编码过程中出现错误,我们将捕获错误并打印错误消息。
  4. 最后,我们打印编码后的 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。
请登录后再评论