Skip to content

go json解析

Published: at 03:43 PM | 3 min read

由于go是静态强类型语言,不像JavaScript那样是动态语言,所以解析json的时候要先定义好解析后的结构体。

以获取豆瓣电影信息接口为例,地址如下:

http://api.douban.com/v2/movie/top250?start=0&count=2

应答结果:

{
	"count": 2,
	"start": 0,
	"total": 250,
	"subjects": [{
		"rating": {
			"max": 10,
			"average": 9.6,
			"stars": "50",
			"min": 0
		},
		"genres": ["\u72af\u7f6a", "\u5267\u60c5"],
		"title": "\u8096\u7533\u514b\u7684\u6551\u8d4e",
		"casts": [{
			"alt": "https:\/\/movie.douban.com\/celebrity\/1054521\/",
			"avatars": {
				"small": "http://img1.doubanio.com\/view\/celebrity\/s_ratio_celebrity\/public\/p17525.webp",
				"large": "http://img1.doubanio.com\/view\/celebrity\/s_ratio_celebrity\/public\/p17525.webp",
				"medium": "http://img1.doubanio.com\/view\/celebrity\/s_ratio_celebrity\/public\/p17525.webp"
			},
			"name": "\u8482\u59c6\u00b7\u7f57\u5bbe\u65af",
			"id": "1054521"
		}, {
			"alt": "https:\/\/movie.douban.com\/celebrity\/1054534\/",
			"avatars": {
				"small": "http://img1.doubanio.com\/view\/celebrity\/s_ratio_celebrity\/public\/p34642.webp",
				"large": "http://img1.doubanio.com\/view\/celebrity\/s_ratio_celebrity\/public\/p34642.webp",
				"medium": "http://img1.doubanio.com\/view\/celebrity\/s_ratio_celebrity\/public\/p34642.webp"
			},
			"name": "\u6469\u6839\u00b7\u5f17\u91cc\u66fc",
			"id": "1054534"
		}, {
			"alt": "https:\/\/movie.douban.com\/celebrity\/1041179\/",
			"avatars": {
				"small": "http://img3.doubanio.com\/view\/celebrity\/s_ratio_celebrity\/public\/p5837.webp",
				"large": "http://img3.doubanio.com\/view\/celebrity\/s_ratio_celebrity\/public\/p5837.webp",
				"medium": "http://img3.doubanio.com\/view\/celebrity\/s_ratio_celebrity\/public\/p5837.webp"
			},
			"name": "\u9c8d\u52c3\u00b7\u5188\u987f",
			"id": "1041179"
		}],
		"collect_count": 1819454,
		"original_title": "The Shawshank Redemption",
		"subtype": "movie",
		"directors": [{
			"alt": "https:\/\/movie.douban.com\/celebrity\/1047973\/",
			"avatars": {
				"small": "http://img1.doubanio.com\/view\/celebrity\/s_ratio_celebrity\/public\/p230.webp",
				"large": "http://img1.doubanio.com\/view\/celebrity\/s_ratio_celebrity\/public\/p230.webp",
				"medium": "http://img1.doubanio.com\/view\/celebrity\/s_ratio_celebrity\/public\/p230.webp"
			},
			"name": "\u5f17\u5170\u514b\u00b7\u5fb7\u62c9\u90a6\u7279",
			"id": "1047973"
		}],
		"year": "1994",
		"images": {
			"small": "http://img1.doubanio.com\/view\/photo\/s_ratio_poster\/public\/p480747492.webp",
			"large": "http://img1.doubanio.com\/view\/photo\/s_ratio_poster\/public\/p480747492.webp",
			"medium": "http://img1.doubanio.com\/view\/photo\/s_ratio_poster\/public\/p480747492.webp"
		},
		"alt": "https:\/\/movie.douban.com\/subject\/1292052\/",
		"id": "1292052"
	}, {
		"rating": {
			"max": 10,
			"average": 9.6,
			"stars": "50",
			"min": 0
		},
		"genres": ["\u5267\u60c5", "\u7231\u60c5", "\u540c\u6027"],
		"title": "\u9738\u738b\u522b\u59ec",
		"casts": [{
			"alt": "https:\/\/movie.douban.com\/celebrity\/1003494\/",
			"avatars": {
				"small": "http://img3.doubanio.com\/view\/celebrity\/s_ratio_celebrity\/public\/p67.webp",
				"large": "http://img3.doubanio.com\/view\/celebrity\/s_ratio_celebrity\/public\/p67.webp",
				"medium": "http://img3.doubanio.com\/view\/celebrity\/s_ratio_celebrity\/public\/p67.webp"
			},
			"name": "\u5f20\u56fd\u8363",
			"id": "1003494"
		}, {
			"alt": "https:\/\/movie.douban.com\/celebrity\/1050265\/",
			"avatars": {
				"small": "http://img1.doubanio.com\/view\/celebrity\/s_ratio_celebrity\/public\/p46345.webp",
				"large": "http://img1.doubanio.com\/view\/celebrity\/s_ratio_celebrity\/public\/p46345.webp",
				"medium": "http://img1.doubanio.com\/view\/celebrity\/s_ratio_celebrity\/public\/p46345.webp"
			},
			"name": "\u5f20\u4e30\u6bc5",
			"id": "1050265"
		}, {
			"alt": "https:\/\/movie.douban.com\/celebrity\/1035641\/",
			"avatars": {
				"small": "http://img3.doubanio.com\/view\/celebrity\/s_ratio_celebrity\/public\/p1399268395.47.webp",
				"large": "http://img3.doubanio.com\/view\/celebrity\/s_ratio_celebrity\/public\/p1399268395.47.webp",
				"medium": "http://img3.doubanio.com\/view\/celebrity\/s_ratio_celebrity\/public\/p1399268395.47.webp"
			},
			"name": "\u5de9\u4fd0",
			"id": "1035641"
		}],
		"collect_count": 1463014,
		"original_title": "\u9738\u738b\u522b\u59ec",
		"subtype": "movie",
		"directors": [{
			"alt": "https:\/\/movie.douban.com\/celebrity\/1023040\/",
			"avatars": {
				"small": "http://img1.doubanio.com\/view\/celebrity\/s_ratio_celebrity\/public\/p1451727734.81.webp",
				"large": "http://img1.doubanio.com\/view\/celebrity\/s_ratio_celebrity\/public\/p1451727734.81.webp",
				"medium": "http://img1.doubanio.com\/view\/celebrity\/s_ratio_celebrity\/public\/p1451727734.81.webp"
			},
			"name": "\u9648\u51ef\u6b4c",
			"id": "1023040"
		}],
		"year": "1993",
		"images": {
			"small": "http://img1.doubanio.com\/view\/photo\/s_ratio_poster\/public\/p1910813120.webp",
			"large": "http://img1.doubanio.com\/view\/photo\/s_ratio_poster\/public\/p1910813120.webp",
			"medium": "http://img1.doubanio.com\/view\/photo\/s_ratio_poster\/public\/p1910813120.webp"
		},
		"alt": "https:\/\/movie.douban.com\/subject\/1291546\/",
		"id": "1291546"
	}],
	"title": "\u8c46\u74e3\u7535\u5f71Top250"
}

为了解析上面的json字符串,定义结构如下:

type (
	Response struct {
		Count   int `json:"count"`
		Start   int `json:"start"`
		Total   int `json:"total"`
		Subject []struct {
			Rating struct {
				Max     int     `json:"max"`
				Average float32 `json:"average"`
				Stars   string  `json:"stars"`
				Min     int     `json:"min"`
			} `json:"rating"`
			Genres []string `json:"genres"`
			Title  string   `json:"title"`
			Casts  []struct {
				Alt     string `json:"alt"`
				Avatars struct {
					Small  string `json:"small"`
					Large  string `json:"large"`
					Medium string `json:"medium"`
				} `json:"avatars"`
			} `json:"casts"`
		} `json:"subjects"`
		Title string `json:"title"`
	}
)

可以看出跟应答字符串里的json格式是对应的,Response是整个应答结果的类型名,里面才是具体的字段,定义的时候一定要注意字段类型不能随便填。

完整代码如下:

package main

import (
	"encoding/json"
	"log"
	"net/http"
)

type (
	Response struct {
		Count   int `json:"count"`
		Start   int `json:"start"`
		Total   int `json:"total"`
		Subject []struct {
			Rating struct {
				Max     int     `json:"max"`
				Average float32 `json:"average"`
				Stars   string  `json:"stars"`
				Min     int     `json:"min"`
			} `json:"rating"`
			Genres []string `json:"genres"`
			Title  string   `json:"title"`
			Casts  []struct {
				Alt     string `json:"alt"`
				Avatars struct {
					Small  string `json:"small"`
					Large  string `json:"large"`
					Medium string `json:"medium"`
				} `json:"avatars"`
			} `json:"casts"`
		} `json:"subjects"`
		Title string `json:"title"`
	}
)

func main() {
	uri := "http://api.douban.com/v2/movie/top250?start=0&count=2"
	resp, err := http.Get(uri)
	if err != nil {
		log.Println("ERROR", err)
		return
	}
	defer resp.Body.Close()
	var res Response
	err = json.NewDecoder(resp.Body).Decode(&res)
	if err != nil {
		log.Println("ERROR", err)
		return
	}
    log.Println(res)
	log.Println(res.Subject[0].Rating)
}

log.Println(res.Subject[0].Rating) 仅打印制定的字段,使用类似的方式获取自己想要的字段的值