英文:
Api Request With Go Parse Json Response
问题
写我的第一个Go应用程序,我正在学习如何进行基本的API调用并解析JSON响应。我相当确定我没有正确地进行类型转换,我的响应是错误的。
如果我创建一些包含数据的数组,我可以得到正确的响应,但是当我将这个更复杂的JSON响应添加到混合中时,事情变得更加混乱,这让我相当确定我没有正确地进行类型转换。
这是我目前的代码,在尝试破坏和尝试解决问题的过程中进行了一些调整:
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
type Payload struct {
Results []Data
}
type Data struct {
PosterPath string `json:"poster_path"`
Adult bool `json:"adult"`
Overview string `json:"overview"`
ReleaseDate string `json:"release_date"`
GenreIDs []int `json:"genre_ids"`
ID int `json:"id"`
OriginalTitle string `json:"original_title"`
OriginalLanguage string `json:"original_language"`
Title string `json:"title"`
BackdropPath string `json:"backdrop_path"`
Popularity float64 `json:"popularity"`
VoteCount int `json:"vote_count"`
Video bool `json:"video"`
VoteAverage float64 `json:"vote_average"`
}
func main() {
url := "https://api.themoviedb.org/3/movie/top_rated?api_key=####APIKEYHERE######"
res, err := http.Get(url)
if err != nil {
panic(err)
}
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
if err != nil {
panic(err)
}
var p Payload
err = json.Unmarshal(body, &p)
if err != nil {
panic(err)
}
for _, data := range p.Results {
fmt.Println(data.PosterPath)
fmt.Println(data.Adult)
fmt.Println(data.Overview)
fmt.Println(data.ReleaseDate)
fmt.Println(data.GenreIDs)
fmt.Println(data.ID)
fmt.Println(data.OriginalTitle)
fmt.Println(data.OriginalLanguage)
fmt.Println(data.Title)
fmt.Println(data.BackdropPath)
fmt.Println(data.Popularity)
fmt.Println(data.VoteCount)
fmt.Println(data.Video)
fmt.Println(data.VoteAverage)
}
}
这是JSON响应的样子:
{
"page": 1,
"results": [
{
"poster_path": "/lIv1QinFqz4dlp5U4lQ6HaiskOZ.jpg",
"adult": false,
"overview": "Under the direction of a ruthless instructor, a talented young drummer begins to pursue perfection at any cost, even his humanity.",
"release_date": "2014-10-10",
"genre_ids": [
18,
10402
],
"id": 244786,
"original_title": "Whiplash",
"original_language": "en",
"title": "Whiplash",
"backdrop_path": "/6bbZ6XyvgfjhQwbplnUh1LSj1ky.jpg",
"popularity": 9.685051,
"vote_count": 1706,
"video": false,
"vote_average": 8.36
}
]
}
有几件事引起了我的注意:
当我尝试将浮点数转换为float64
时,我对从float32
转换的方式感到困惑。
在JSON响应中有一个数组,当尝试进行类型转换时会感到困惑。
"genre_ids": [
36,
18,
53,
10752
]
希望这可以帮助到你!
英文:
Writing my first Go Application I am learning to make a basic api call and parse the json response. I am pretty sure I am not casting my types correctly and my response is
false
0
0
0
0 false
0
If I create a few arrays with data in them I can get that response but when I add this more complexed json response to the mix things get more confusing which leads me to be quite positive I am not casting correctly.
This is my current code after playing around and changing things in order to break stuff and try and figure things out.
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
type Payload struct {
results Data
}
type Data struct {
poster_path string
adult bool
overview string
release_date string
genre_ids int
id int
original_title string
original_language string
title string
backdrop_path string
popularity float64
vote_count int
video bool
vote_average float64
}
type poster_path map[string]string
type adult map[string]bool
type overview map[string]string
type release_date map[string]string
type genre_ids map[string]int
type id map[string]int
type original_title map[string]string
type original_language map[string]string
type title map[string]string
type backdrop_path map[string]string
type popularity map[string]float64
type vote_count map[string]int
type video map[string]bool
type vote_average map[string]float64
func main() {
// http://image.tmdb.org/t/p/w185
url := "https://api.themoviedb.org/3/movie/top_rated?api_key=####APIKEYHERE######"
res, err := http.Get(url)
if err != nil {
panic(err)
}
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
if err != nil {
panic(err)
}
var p Payload
err = json.Unmarshal(body, &p)
if err != nil {
panic(err)
}
fmt.Println(
p.results.poster_path, "\n", p.results.adult,
p.results.overview, "\n", p.results.release_date,
p.results.genre_ids, "\n", p.results.id,
p.results.original_title, "\n", p.results.original_language,
p.results.title, "\n", p.results.backdrop_path,
p.results.popularity, "\n", p.results.vote_count,
p.results.video, "\n", p.results.vote_average,
)
}
This is what the JSON response looks like,
{
"page": 1,
"results": [
{
"poster_path": "/lIv1QinFqz4dlp5U4lQ6HaiskOZ.jpg",
"adult": false,
"overview": "Under the direction of a ruthless instructor, a talented young drummer begins to pursue perfection at any cost, even his humanity.",
"release_date": "2014-10-10",
"genre_ids": [
18,
10402
],
"id": 244786,
"original_title": "Whiplash",
"original_language": "en",
"title": "Whiplash",
"backdrop_path": "/6bbZ6XyvgfjhQwbplnUh1LSj1ky.jpg",
"popularity": 9.685051,
"vote_count": 1706,
"video": false,
"vote_average": 8.36
}
}
A few things that stand out to me,
When I tried to cast the float I was confused about casting from float32
to float64
There is an array inside the json response which was confusing when trying to cast,
"genre_ids": [
36,
18,
53,
10752
],
答案1
得分: 4
这是一个常见的初学者错误。由于语言设计的原因,encoding/json
包只能将数据解组到导出字段中。
根据 encoding/json
包的说明:
> 为了将 JSON 解组到结构体中,Unmarshal 会将传入的对象键与 Marshal 使用的键进行匹配(可以是结构体字段名或其标签),优先选择精确匹配,但也接受不区分大小写的匹配。
> Unmarshal 只会设置结构体的导出字段。
要导出一个字段,只需将名称的首字母大写。例如:
type Payload struct {
Results Data
}
而不是
type Payload struct {
results Data
}
英文:
Is a common beginners mistake. Due to language design, the encoding/json
package can only unmarshal into exported fields.
From the encoding/json
package:
> To unmarshal JSON into a struct, Unmarshal matches incoming object keys to
> the keys used by Marshal (either the struct field name or its tag),
> preferring an exact match but also accepting a case-insensitive match.
> Unmarshal will only set exported fields of the struct.
To export a field, simply use a capital first letter of the name. Eg.:
type Payload struct {
Results Data
}
instead of
type Payload struct {
results Data
}
答案2
得分: 1
首先,你在JSON中的results
末尾缺少一个闭合的方括号]
。
其次,你没有按照接收到的JSON来构建你的结构体。
最后,在处理Unmarshal/marshal时,在每个导出字段的结构体后使用JSON标签,以帮助Go检测适当的字段(如果你根据Unmarshal/marshal如何识别字段的方式命名字段,则不需要这样做)。
type Payload struct {
Page int
Results []Data
}
type Data struct {
PosterPath string `json:"poster_path"`
Adult bool `json:"adult"`
Overview string `json:"overview"`
ReleaseDate string `json:"release_date"`
GenreIds []int `json:"genre_ids"`
Id int `json:"id"`
OriginalTitle string `json:"original_title"`
OriginalLanguage string `json:"original_language"`
Title string `json:"title"`
BackdropPath string `json:"backdrop_path"`
Popularity float64 `json:"popularity"`
VoteCount int `json:"vote_count"`
Video bool `json:"video"`
VoteAverage float64 `json:"vote_average"`
}
请注意,GenreIds
也必须是[]int
以匹配JSON数据。在Go中不使用驼峰命名法是一个好主意。
参考:https://play.golang.org/p/VduPD9AY84
英文:
First of all, you are missing a closing square bracket ]
at the end of results
in your JSON.
Secondly, you did not structure your structs according to the JSON you receive.
Lastly, use JSON tags after each exported field in your struct when dealing with Unmarshal/marshaling to help Go detect the appropriate fields (not necessary if you name the fields according to how Unmarshal/marshal identify fields.
type Payload struct {
Page int
Results []Data
}
type Data struct {
PosterPath string `json:"poster_path"`
Adult bool `json:"adult"`
Overview string `json:"overview"`
ReleaseDate string `json:"release_date"`
GenreIds []int `json:"genre_ids"`
Id int `json:"id"`
OriginalTitle string `json:"original_title"`
OriginalLanguage string `json:"original_language"`
Title string `json:"title"`
BackdropPath string `json:"backdrop_path"`
Popularity float64 `json:"popularity"`
VoteCount int `json:"vote_count"`
Video bool `json:"video"`
VoteAverage float64 `json:"vote_average"`
}
Note that GenreIds
has to be []int
to match the JSON data as well. And it's a good idea not to use CamelCase in Go.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论