Go进阶-JSON和YAML的操作
一、JSON数据操作
Go语言标准库已经内置了encoding/json库,不需要额外安装。
JSON方法大全
写入JSON数据
需要配置os的文件操作方法进行
file, _ := os.Create("cats.json")
err := json.NewEncoder(file).Encode()
// 还可以在写入的时候进行格式优化
encoder := json.NewEncoder(file)
// 设置漂亮格式(缩进)并写入data数据到文件
encoder.SetIndent("", " ").Encode(data)
读取json数据
需要配置os的文件操作方法进行
file, _ := os.Open("cats.json")
// 读取文件数据传入到data指针
err := json.NewDecoder(file).Decode(&data)
编码和解码
编码Go对象成JSON数据和解码JSON数据成Go对象
// 编码Go对象成JSON数据
data := map[string]interface{}{"name": "miaomi", "quantity": 123, "breed": "ragdoll"}
jsonBytes, _ := json.Marshal(data)
fmt.Println(string(jsonBytes))
/* 运行结果如下
{"breed":"ragdoll","name":"miaomi","quantity":123}
*/
// 解码JSON数据成Go对象
json_data := `{"name": "miaomi", "quantity": 123, "breed": "ragdoll"}`
var result map[string]interface{}
_ = json.Unmarshal([]byte(json_data), &result)
fmt.Println(result)
/* 运行结果如下
map[breed:ragdoll name:miaomi quantity:123]
*/
美化JSON格式
data := map[string]interface{}{"name": "miaomi", "quantity": 123, "breed": "ragdoll"}
jsonBytes, _ := json.MarshalIndent(data, "", " ")
fmt.Println(string(jsonBytes))
/* 运行结果如下
{
"breed": "ragdoll",
"name": "miaomi",
"quantity": 123
}
*/
读取json文件
示例都通过该JSON文件内容为基础。json文件cats.json文件内容如下:
{
"name": "miaomi",
"quantity": 123,
"variety": [
"sphynx",
"ragdoll",
"persian",
"siamese"
],
"prices": {
"sphynx": 800,
"ragdoll": 1300,
"persian": 4700,
"siamese": 2300
}
}
从JSON 文件读取嵌套结构体
一般在知道json数据返回格式后,才方便使用结构体,灵活性太差。
【示例】代码如下所示:
package main
import (
"encoding/json"
"fmt"
"os"
)
type Prices struct {
Sphynx int `json:"sphynx"`
Ragdoll int `json:"ragdoll"`
Persian int `json:"persian"`
Siamese int `json:"siamese"`
}
type Shop struct {
Name string `json:"name"`
Quantity int `json:"quantity"`
Variety []string `json:"variety"`
Price_list Prices `json:"prices"`
}
func main() {
file, err := os.Open("cats.json")
if err != nil {
panic(err)
}
defer file.Close()
// 定义data为结构体Shop数据类型格式
var data Shop
decoder := json.NewDecoder(file)
// 读取文件里面的JSON数据并赋值给data指针
err = decoder.Decode(&data)
if err != nil {
panic(err)
}
// 打印结构体里的变量值
fmt.Println("Ragdoll品种的价格:", data.Price_list.Ragdoll)
fmt.Println("猫的种类:", data.Variety)
}
/* 运行结果如下
Ragdoll品种的价格: 1300
猫的种类: [sphynx ragdoll persian siamese]
*/
从JSON 文件读取map数据
【示例】代码如下所示:
package main
import (
"encoding/json"
"fmt"
"os"
)
func main() {
file, err := os.Open("cats.json")
if err != nil {
panic(err)
}
defer file.Close()
// 定义data为map数据类型格式
var data map[string]interface{}
// 读取文件里面的JSON数据并赋值给data指针
decoder := json.NewDecoder(file)
err = decoder.Decode(&data)
if err != nil {
panic(err)
}
fmt.Println("整体数据结构:", data)
fmt.Println("prices里的数据", data["prices"])
/* 获取prices里面persian品种的价格
定义的map后面数据是interface{}类型,所以需要转化一个数据类型 */
a := data["prices"].(map[string]interface{})["persian"].(float64)
fmt.Println("persian品种的价格:", a)
}
/* 运行结果如下
整体数据结构: map[name:miaomi prices:map[persian:4700 ragdoll:1300 siamese:2300 sphynx:800] quantity:123 variety:[sphynx ragdoll persian siamese]]
prices里的数据 map[persian:4700 ragdoll:1300 siamese:2300 sphynx:800]
persian品种的价格: 4700
*/
写入json数据
写入嵌套结构体到 JSON 文件
【示例】代码如下所示:
package main
import (
"encoding/json"
"fmt"
"os"
)
type Prices struct {
Sphynx int `json:"sphynx"`
Ragdoll int `json:"ragdoll"`
Persian int `json:"persian"`
Siamese int `json:"siamese"`
}
type Shop struct {
Name string `json:"name"`
Quantity int `json:"quantity"`
Variety []string `json:"variety"`
Price_list Prices `json:"prices"`
}
func main() {
// 初始化结构体的值
shop := Shop{
Name: "miaomi",
Quantity: 123,
Variety: []string{"sphynx", "ragdoll", "persian", "siamese"},
Price_list: Prices{
Sphynx: 800,
Ragdoll: 1300,
Persian: 4700,
Siamese: 2300,
},
}
// 打开创建JSON文件: cats.json
file, err := os.Create("cats.json")
if err != nil {
panic(err)
}
defer file.Close()
// 写入结构体数据到JSON文件中
encoder := json.NewEncoder(file)
encoder.SetIndent("", " ") // 设置漂亮格式(缩进)
err = encoder.Encode(shop)
if err != nil {
panic(err)
}
}
通过map数据写入到JSON文件
【示例】代码如下所示:
package main
import (
"encoding/json"
"fmt"
"os"
)
func main() {
// 初始化赋值变量data,数据类型为map
data := map[string]interface{}{
"name": "miaomi",
"quantity": 123,
"prices": map[string]float64{
"sphynx": 800,
"ragdoll": 1300,
"persian": 4700,
"siamese": 2300,
},
"variety": []string{
"sphynx",
"ragdoll",
"persian",
"siamese",
},
}
// 打开创建JSON文件: cats.json
file, err := os.Create("cats2.json")
if err != nil {
panic(err)
}
defer file.Close()
// 写入结构体数据到JSON文件中
encoder := json.NewEncoder(file)
encoder.SetIndent("", " ") // 设置漂亮格式(缩进)
err = encoder.Encode(data)
if err != nil {
panic(err)
}
}
二、YAML数据操作
三方库( gopkg.in/yaml.v3)
它支持将YAML文件解析为结构体、从结构体生成 YAML、直接处理 map 或切片等。
安装三方库:gopkg.in/yaml.v3
go get gopkg.in/yaml.v3
go.mod文件示例:
module myapp
go 1.22
require gopkg.in/yaml.v3 v3.0.1
导入库,如下:
import "gopkg.in/yaml.v3"
YAML方法大全
核心函数(Marshal / Unmarshal)
Marshal函数:将结构体(struct)或映射(map)解析成YAML
data := map[string]interface{}{"name": "miaomi", "quantity": 123, "breed": "ragdoll"}
yaml_data, err := yaml.Marshal(data)
Unmarshal函数:将YAML解析成结构体(struct)或映射(map)
var cfg Config
err := yaml.Unmarshal(yaml_data, &cfg)
流式读写(Decoder / Encoder)
流式读取(Decoder):
file, _ := os.Open("cats.json")
// 读取文件数据传入到data指针
err := yaml.NewDecoder(file).Decode(&data)
流式写入(Encoder):
// 初始化赋值data变量
var data Config
file, _ := os.Create("cats.json")
// 写入data数据到文件中
encoder, err := yaml.NewEncoder(file)
// 美化格式
encoder.SetIndent(2)
encoder.Encode(data)
读取yaml文件数据
示例config.yaml文件:
server:
port: 8080
host: localhost
database:
user: admin
password: secret
将YAML解析成结构体读取数据
【示例】代码如下所示:
package main
import (
"fmt"
"os"
"gopkg.in/yaml.v3"
)
/* 创建结构体,将内部结构体拆分出来
以Config为主结构体,Server和Database为子结构体
*/
type Server struct {
Port int `yaml:"port"`
Host string `yaml:"host"`
}
type Database struct {
User string `yaml:"user"`
Password string `yaml:"password"`
}
type Config struct {
Server Server `yaml:"server"`
Database Database `yaml:"database"`
}
func main(){
// 读取yaml文件内容
file, err := os.ReadFile("config.yaml")
if err != nil {
fmt.Println("读取文件失败:", err)
}
// 将读取的文件对象内容解析到结构体中,再从结构体中获取变量值
var config Config
err = yaml.Unmarshal(file, &config)
if err != nil {
fmt.Println("解析 YAML 失败:", err)
}
// 输出结构体值
fmt.Printf("%+v\n", config)
}
/* 运行结果如下
{Server:{Port:8080 Host:localhost} Database:{User:admin Password:secret}}
*/
将YAML解析成map数据
【示例】代码如下所示:
package main
import (
"fmt"
"os"
"gopkg.in/yaml.v3"
)
func main(){
// 读取yaml文件内容
file, err := os.ReadFile("config.yaml")
if err != nil {
fmt.Println("读取文件失败:", err)
}
// 将读取的文件对象内容解析到map中,再从map中进行处理
var data map[string]interface{}
err = yaml.Unmarshal(file, &data)
if err != nil {
fmt.Println("解析 YAML 失败:", err)
}
fmt.Println(data)
}
/* 运行结果如下
map[database:map[password:secret user:admin] server:map[host:localhost port:8080]]
*/
写入yaml文件数据
注意:
1.Go map 是无序的,所以生成的 YAML 字段顺序可能和你写的 map 顺序不一样。
2.如果需要固定顺序,可以用结构体代替map,或者用yaml.Node手动控制。
将结构体数据写入YAML文件
【示例】代码如下所示:
package main
import (
"fmt"
"os"
"gopkg.in/yaml.v3"
)
/* 创建结构体,将内部结构体拆分出来
以Config为主结构体,Server和Database为子结构体
*/
type Server struct {
Port int `yaml:"port"`
Host string `yaml:"host"`
}
type Database struct {
User string `yaml:"user"`
Password string `yaml:"password"`
}
type Config struct {
Server Server `yaml:"server"`
Database Database `yaml:"database"`
}
func main(){
// 初始化赋值Config结构体
config := Config{
Server: Server{
Port: 8080,
Host: "localhost",
},
Database: Database{
User: "admin",
Password: "secret",
},
}
// 将结构体解析成yaml数据
data, err := yaml.Marshal(&config)
if err != nil {
fmt.Println("转换为 YAML 失败:", err)
}
// 将解析的yaml数据写入到文件中
err = os.WriteFile("struct_to_yaml.yaml", data, 0644)
if err != nil {
fmt.Println("写入文件失败:", err)
}
}
写入的struct_to_yaml.yaml文件内容如下:
server:
port: 8080
host: localhost
database:
user: admin
password: secret
将map数据写入YAML文件
【示例】代码如下所示:
package main
import (
"fmt"
"os"
"gopkg.in/yaml.v3"
)
func main(){
// 初始化map对象并赋值结构
mapdata := map[string]interface{}{"name": "Jimmy", "age": 23,
"spec": map[string]interface{}{
"server": map[string]interface{}{"host": "127.0.0.1", "port": 8080},
"database": map[string]interface{}{"user": "root", "password": "e3uh339j5ih82d"},
},
"white_list": []string{"192.168.1.0/24", "172.16.10.187", "10.8.0.0/16"},
}
// 将map结构和数据解析成yaml对象
data, err := yaml.Marshal(&mapdata)
if err != nil {
fmt.Println("转换为 YAML 失败:", err)
}
// 将解析的yaml数据写入到文件中
err = os.WriteFile("map_to_yaml.yaml", data, 0644)
if err != nil {
fmt.Println("写入文件失败:", err)
}
}
写入的map_to_yaml.yaml文件内容如下:
age: 23
name: Jimmy
spec:
database:
password: e3uh339j5ih82d
user: root
server:
host: 127.0.0.1
port: 8080
white_list:
- 192.168.1.0/24
- 172.16.10.187
- 10.8.0.0/16