在Go语言的实际开发中,JSON是前后端交互、服务间通信常用的数据格式,其中JSON数组的解析是高频操作。很多开发者在尝试将JSON数组解析到自定义结构体切片时,会因为结构体定义不规范、解析方法使用错误等问题导致解析失败,下面我们就来详细讲解正确的解析方式。

定义匹配的自定义结构体
要将JSON数组解析到自定义结构体切片,首先需要定义和JSON数组元素结构匹配的结构体,并且需要给结构体字段添加正确的JSON标签,标签名要和JSON中的字段名对应,否则解析时会出现字段值丢失的情况。
假设我们有如下格式的JSON数组,数组中的每个元素都包含用户ID、用户名和用户年龄三个字段:
[
{"id": 1, "name": "张三", "age": 25},
{"id": 2, "name": "李四", "age": 28},
{"id": 3, "name": "王五", "age": 22}
]
对应的自定义结构体定义如下,注意JSON标签的写法,标签内的名称和JSON中的字段名完全一致:
type User struct {
ID int `json:"id"` // 对应JSON中的id字段
Name string `json:"name"` // 对应JSON中的name字段
Age int `json:"age"` // 对应JSON中的age字段
}
使用encoding/json包解析
Go语言标准库的encoding/json包提供了JSON解析的能力,解析JSON数组到结构体切片主要使用json.Unmarshal函数。需要注意的是,我们需要先声明一个对应结构体类型的切片变量,然后将该变量的指针传入json.Unmarshal函数。
完整的解析代码示例如下:
package main
import (
"encoding/json"
"fmt"
)
type User struct {
ID int `json:"id"`
Name string `json:"name"`
Age int `json:"age"`
}
func main() {
// 待解析的JSON数组字符串
jsonStr := `[
{"id": 1, "name": "张三", "age": 25},
{"id": 2, "name": "李四", "age": 28},
{"id": 3, "name": "王五", "age": 22}
]`
// 声明User结构体切片变量
var userList []User
// 执行解析操作,传入切片变量的指针
err := json.Unmarshal([]byte(jsonStr), &userList)
if err != nil {
fmt.Println("解析失败,错误信息:", err)
return
}
// 遍历解析后的切片,验证结果
for _, user := range userList {
fmt.Printf("用户ID:%d,用户名:%s,年龄:%dn", user.ID, user.Name, user.Age)
}
}
常见解析错误及解决方法
结构体字段标签不匹配
如果结构体字段的JSON标签和JSON中的字段名不一致,解析后该字段的值会是零值。比如将json:"id"写成json:"userId",那么解析后ID字段的值会是0。解决方法是确保结构体JSON标签和JSON中的字段名完全一致,注意大小写敏感。
未传入切片指针
如果调用json.Unmarshal时,第二个参数传入的是切片变量而不是指针,解析后切片不会有任何数据。因为Go语言是值传递,传入切片变量时,函数内修改的是切片的副本,不会影响原变量。必须传入切片的指针,也就是&userList的形式。
JSON格式错误
如果传入的JSON字符串格式不正确,比如数组缺少闭合括号、字段名没有用双引号包裹等,json.Unmarshal会返回错误。此时可以通过错误信息定位JSON格式问题,修正后再重新解析。
动态JSON数组的处理
如果JSON数组中的元素结构不固定,无法提前定义对应的结构体,可以使用[]map[string]interface{}类型来接收解析结果,之后再根据实际需求做类型断言获取对应字段的值。
示例代码如下:
package main
import (
"encoding/json"
"fmt"
)
func main() {
jsonStr := `[
{"id": 1, "name": "张三", "age": 25},
{"id": 2, "name": "李四", "score": 90.5}
]`
var data []map[string]interface{}
err := json.Unmarshal([]byte(jsonStr), &data)
if err != nil {
fmt.Println("解析失败,错误信息:", err)
return
}
for _, item := range data {
fmt.Println("当前元素内容:", item)
// 根据存在的字段做对应处理
if name, ok := item["name"].(string); ok {
fmt.Println("用户名:", name)
}
}
}
注意使用interface{}接收字段值时,一定要做类型断言,避免直接类型转换导致panic。
GoJSON解析结构体切片encoding_json自定义结构体修改时间:2026-07-20 07:12:24