如何在Golang中读取和写入JSON文件
JSON是前后端数据交互、配置文件存储场景中最常用的数据格式之一,Golang标准库内置了encoding/json包,提供了完整的JSON编解码能力,不需要引入第三方依赖就能完成JSON文件的读写操作。本文将详细介绍Golang中读取和写入JSON文件的具体实现方法,包含基础示例和常见场景处理。
一、核心概念与准备工作
在Golang中处理JSON文件,核心是将JSON数据与结构体(struct)进行映射,或者处理map[string]interface{}类型的动态数据。首先我们需要引入必要的标准库:
import (
"encoding/json" // 提供JSON编解码能力
"fmt" // 用于打印输出
"os" // 提供文件读写操作
)如果使用结构体映射JSON数据,需要保证结构体字段的首字母大写(公开字段),同时可以通过结构体标签(tag)指定JSON字段名,避免和Go的命名规范冲突。
二、写入JSON文件
写入JSON文件的流程分为三步:准备要存储的数据、将数据编码为JSON格式、将JSON内容写入文件。下面的示例演示了如何将结构体数据写入JSON文件。
// 定义用户结构体,通过json标签指定JSON中的字段名
type User struct {
Name string `json:"name"` // 姓名,对应JSON中的name字段
Age int `json:"age"` // 年龄,对应JSON中的age字段
Email string `json:"email"` // 邮箱,对应JSON中的email字段
}
func writeJSONToFile() error {
// 准备要写入的数据
user := User{
Name: "张三",
Age: 25,
Email: "zhangsan@ipipp.com",
}
// 将数据编码为格式化的JSON,第二个参数是前缀,第三个是缩进字符串
jsonData, err := json.MarshalIndent(user, "", " ")
if err != nil {
return fmt.Errorf("JSON编码失败: %v", err)
}
// 将JSON数据写入文件,0666是文件权限,代表所有用户可读可写
err = os.WriteFile("user.json", jsonData, 0666)
if err != nil {
return fmt.Errorf("写入文件失败: %v", err)
}
fmt.Println("JSON文件写入成功")
return nil
}如果需要写入动态数据,也可以使用map[string]interface{}类型,不需要提前定义结构体,适合字段不固定的场景:
func writeDynamicJSONToFile() error {
// 准备动态数据
data := map[string]interface{}{
"app_name": "测试应用",
"version": "1.0.0",
"features": []string{"用户登录", "数据导出", "消息通知"},
"config": map[string]interface{}{
"max_conn": 100,
"timeout": 30,
},
}
jsonData, err := json.MarshalIndent(data, "", " ")
if err != nil {
return fmt.Errorf("JSON编码失败: %v", err)
}
err = os.WriteFile("config.json", jsonData, 0666)
if err != nil {
return fmt.Errorf("写入文件失败: %v", err)
}
fmt.Println("动态JSON文件写入成功")
return nil
}三、读取JSON文件
读取JSON文件的流程分为三步:读取文件内容、将JSON数据解码为Go的数据结构、使用解析后的数据。下面的示例对应上面的结构体写入场景,演示如何读取并解析JSON文件。
func readJSONFromFile() error {
// 读取文件内容
jsonData, err := os.ReadFile("user.json")
if err != nil {
return fmt.Errorf("读取文件失败: %v", err)
}
// 定义接收数据的结构体
var user User
// 将JSON数据解码到结构体中
err = json.Unmarshal(jsonData, &user)
if err != nil {
return fmt.Errorf("JSON解码失败: %v", err)
}
fmt.Printf("读取到的用户数据: 姓名=%s, 年龄=%d, 邮箱=%s\n", user.Name, user.Age, user.Email)
return nil
}如果是读取动态的JSON数据,可以使用map[string]interface{}接收,不需要提前知道JSON的具体结构:
func readDynamicJSONFromFile() error {
jsonData, err := os.ReadFile("config.json")
if err != nil {
return fmt.Errorf("读取文件失败: %v", err)
}
var config map[string]interface{}
err = json.Unmarshal(jsonData, &config)
if err != nil {
return fmt.Errorf("JSON解码失败: %v", err)
}
fmt.Println("读取到的配置数据:")
for key, value := range config {
fmt.Printf(" %s: %v\n", key, value)
}
return nil
}四、完整示例与调用
下面的代码将上面的读写函数整合,可以直接运行测试完整流程:
package main
import (
"encoding/json"
"fmt"
"os"
)
type User struct {
Name string `json:"name"`
Age int `json:"age"`
Email string `json:"email"`
}
func writeJSONToFile() error {
user := User{
Name: "张三",
Age: 25,
Email: "zhangsan@ipipp.com",
}
jsonData, err := json.MarshalIndent(user, "", " ")
if err != nil {
return fmt.Errorf("JSON编码失败: %v", err)
}
err = os.WriteFile("user.json", jsonData, 0666)
if err != nil {
return fmt.Errorf("写入文件失败: %v", err)
}
fmt.Println("JSON文件写入成功")
return nil
}
func readJSONFromFile() error {
jsonData, err := os.ReadFile("user.json")
if err != nil {
return fmt.Errorf("读取文件失败: %v", err)
}
var user User
err = json.Unmarshal(jsonData, &user)
if err != nil {
return fmt.Errorf("JSON解码失败: %v", err)
}
fmt.Printf("读取到的用户数据: 姓名=%s, 年龄=%d, 邮箱=%s\n", user.Name, user.Age, user.Email)
return nil
}
func main() {
// 先写入JSON文件
if err := writeJSONToFile(); err != nil {
fmt.Println("写入失败:", err)
return
}
// 再读取JSON文件
if err := readJSONFromFile(); err != nil {
fmt.Println("读取失败:", err)
return
}
}五、注意事项
- 结构体字段必须首字母大写才能被JSON包访问到,否则编码解码时会忽略该字段。
- 如果JSON字段名和结构体字段名不一致,必须通过
json:"字段名"的标签指定映射关系。 - 使用
os.WriteFile写入文件时,如果文件已存在会直接覆盖,如果需要追加内容,需要先打开文件并设置追加模式。 - 解码动态JSON到
map[string]interface{}时,数字类型默认会被解析为float64,如果需要其他数字类型,需要手动做类型转换。 - 处理文件操作时建议 always 做错误判断,避免程序因为文件不存在、权限不足等问题崩溃。
GolangJSON文件读写encoding_json结构体映射Go文件操作修改时间:2026-05-23 16:10:37