Golang中如何将[]byte切片转换为可操作的JSON?
Go中解析多维JSON的基础方法
首先纠正你代码里的JSON语法错误:原JSON中track数组的第一个对象里,artist字段结尾多了个逗号,导致结构非法,修正后的JSON如下:
bytt := []byte(`{"tracks":{"track":[{"name":"Yellow","duration":"276","artist":{"name":"coldplay"}},{"name":"red","duration":"345","artist":{"name":"somename"}}]}}`)
Go是强类型语言,没有PHP/JS那种动态多维数组,要解析并操作JSON,主要有两种常用方式:
1. 结构体映射(推荐,类型安全)
先定义和JSON结构完全匹配的结构体,再用encoding/json包的Unmarshal方法解析,操作时直接访问结构体字段即可。
示例代码
package main import ( "encoding/json" "fmt" ) // 定义对应JSON结构的结构体 type Artist struct { Name string `json:"name"` // json标签指定与JSON字段的映射关系 } type Track struct { Name string `json:"name"` Duration string `json:"duration"` Artist Artist `json:"artist"` } type MusicResponse struct { Tracks struct { TrackList []Track `json:"track"` } `json:"tracks"` } func main() { bytt := []byte(`{"tracks":{"track":[{"name":"Yellow","duration":"276","artist":{"name":"coldplay"}},{"name":"red","duration":"345","artist":{"name":"somename"}}]}}`) var resp MusicResponse // 将[]byte解析到结构体指针 err := json.Unmarshal(bytt, &resp) if err != nil { fmt.Println("JSON解析失败:", err) return } // 遍历歌曲列表 for idx, track := range resp.Tracks.TrackList { fmt.Printf("第%d首歌:\n", idx+1) fmt.Printf(" 名称:%s\n", track.Name) fmt.Printf(" 时长:%s秒\n", track.Duration) fmt.Printf(" 歌手:%s\n\n", track.Artist.Name) } }
关键说明
- 结构体字段必须首字母大写,否则
encoding/json包无法访问(Go中只有导出字段能被外部包读取)。 json:"xxx"标签用来关联JSON中的小写字段和结构体的大写字段,必须和JSON字段名完全一致。
2. 动态解析(map[string]interface{})
如果JSON结构不确定,或者不想定义结构体,可以用map[string]interface{}类型解析,类似PHP/JS的关联数组,但需要手动做类型断言才能访问具体值。
示例代码
package main import ( "encoding/json" "fmt" ) func main() { bytt := []byte(`{"tracks":{"track":[{"name":"Yellow","duration":"276","artist":{"name":"coldplay"}},{"name":"red","duration":"345","artist":{"name":"somename"}}]}}`) var data map[string]interface{} err := json.Unmarshal(bytt, &data) if err != nil { fmt.Println("JSON解析失败:", err) return } // 逐层类型断言并访问 tracks := data["tracks"].(map[string]interface{}) trackList := tracks["track"].([]interface{}) for _, item := range trackList { track := item.(map[string]interface{}) // 断言为string类型,失败会panic,生产环境可加ok判断 name := track["name"].(string) duration := track["duration"].(string) artist := track["artist"].(map[string]interface{}) artistName := artist["name"].(string) fmt.Printf("歌曲:%s | 时长:%s | 歌手:%s\n", name, duration, artistName) } }
关键说明
interface{}是Go的空接口,可以存储任意类型的值,解析后需要用.(类型)断言成具体类型才能操作。- 生产环境建议用
val, ok := obj.(类型)的安全断言方式,避免panic:artist, ok := track["artist"].(map[string]interface{}) if !ok { fmt.Println("artist字段类型错误") continue }
内容的提问来源于stack exchange,提问作者black
相关产品推荐
相关产品推荐

