在运行时发生的Golang GET请求JSON类型错误。

huangapple go评论106阅读模式
英文:

golang GET request json type error at runtime

问题

我正在尝试使用Golang中的USA Today的RESTful API编写一个小应用程序,但是当我尝试解析API的GET请求时,似乎出现了类型转换错误。我的程序可以编译,这让我认为类型是正确的,但在运行时程序崩溃了。

我对如何映射传入的JSON有一个很好的想法,其中你没有预先定义的结构,可以使用类型interface{},参考链接:http://blog.golang.org/json-and-go

以下是我的Golang代码示例:

// 发送GET请求到API
resp, err := http.Get("http://api.usatoday.com/open/articles/topnews/home?count=10&days=0&page=0&encoding=json&api_key=myApiKey")

if err == nil {
    body, err := ioutil.ReadAll(resp.Body)
    if err == nil {
        var data interface{}
        json.Unmarshal(body, &data)

        var m = data.(map[string][]interface{})
        var articles = m["stories"]
        var newArticle interface{}

        for newArticle = range articles {
            var n = newArticle.(map[string]string)

            fmt.Printf("<h2>Title: " + n["title"] + "</h2>")
            fmt.Printf("<p>description: " + n["description"] + "</p>")
            fmt.Printf("<p>link to article: " + n["link"] + "</p>")
        }

    } else {
        fmt.Println(err)
    }

} else {
    fmt.Println(err)
}

以下是GET请求响应的一个小例子:

{
    "stories": [{
        "description": "Despite the fact that shoppers descended upon stores after giving thanks, Black Friday wasn't without its share of brawls.",
        "guid": [{
            "isPermalink": "true",
            "value": "http://apidata.usatoday.com/story/news/nation-now/2013/11/29/black-friday-police-violence/3783467/?kjnd=Pvzhnh75%2BZ3dnzxHVv571HQOfzKReZECsSPCBGnAiXlbHijpqdc3TQoe4dYfzVlB-8d81f9e3-0b56-421e-a5da-121f9eb83de3_E50GPTZL1%2FYloJsxpxSnp8AhoO2O9prQtDTYiwN3sbV0SfQ5wriH1zooo6XgNPTr"
        }],
        "link": "http://apidata.usatoday.com/story/news/nation-now/2013/11/29/black-friday-police-violence/3783467/?kjnd=LOCSg6KVoQR3pwnZyGmcgcDZXwce0MwglPkURuQ%2BzMkUdNzQ2GXJr%2FPfLCl4Hf38-8d81f9e3-0b56-421e-a5da-121f9eb83de3_Zp5d44u%2F3U2IkXWRbNP0OwyXjRkEgShxoJC0wp7%2FOJoFPCI979Zw4qgNkWkOG1x1",
        "pubDate": "Fri, 29 Nov 2013 02:57:43 GMT",
        "title": "Black Friday frenzy leads to reports of violence"
    }, {
        "description": "President Obama's law faces hurdles beyond the Supreme Court case on the birth control mandate.",
        "guid": [{
            "isPermalink": "true",
            "value": "http://apidata.usatoday.com/story/news/politics/2013/11/29/supreme-court-obamacare-lawsuits-irs/3760811/?kjnd=sCqadf244XkWTNcS0zAI%2Ba25XsnxwAX3ahu8NP0bzKdU4Kx31rJsa0cWlhvnwMl8-8d81f9e3-0b56-421e-a5da-121f9eb83de3_wtrtyHNPao7CqrB0IR7%2Bj3GFwJMhSYFSrOrrGZCkX2BStipIyyDtQoTLLFCGoLj0"
        }],
        "link": "http://apidata.usatoday.com/story/news/politics/2013/11/29/supreme-court-obamacare-lawsuits-irs/3760811/?kjnd=Be2GdDxc2cZdIOPiCpcL9vz%2FFvmT859xSGoVutxwurqJ%2FCwvTt8vjs2s9MHzI1hO-8d81f9e3-0b56-421e-a5da-121f9eb83de3_88mb%2BwbADj1MvtG9%2BiYMhVS43CRGBEVdn0v5QJsORviARUA3qR0iE9LBr7NpNrT7",
        "pubDate": "Fri, 29 Nov 2013 11:12:08 GMT",
        "title": "Long-shot legal challenges to health care law abound"
    }]
}

最后,以下是运行时的错误信息:

panic: interface conversion: interface is map[string]interface {}, not map[string][]interface {}

我不太确定应该如何解决这个问题,所以如果有任何在Golang中使用RESTful API的经验的人能提供一些见解,将不胜感激!

英文:

im trying to write a small app using usa today's RESTful api in golang, but it seems i have an error in type conversion when trying to parse the GET request from the api. My program compiles which makes me think the types are right, but at run time my program crashes

i got a good idea how to map incoming json in which you don't have premade structures for using the type interface {} from
http://blog.golang.org/json-and-go

here's what my golang code looks like:

// get request to API
resp, err := http.Get(&quot;http://api.usatoday.com/open/articles/topnews/home?count=10&amp;days=0&amp;page=0&amp;encoding=json&amp;api_key=myApiKey&quot;)

if(err == nil){
	body, err := ioutil.ReadAll(resp.Body)
	if(err == nil) {
		var data interface{}
		json.Unmarshal(body, &amp;data)
		
		var m = data.(map[string] []interface{})			
		var articles = m[&quot;stories&quot;]
		var newArticle interface {}
		
		for newArticle = range articles {
			var n = newArticle.(map[string] string)
			
			fmt.Printf(&quot;&lt;h2&gt;Title: &quot; + n[&quot;title&quot;] + &quot;&lt;/h2&gt;&quot;)
			fmt.Printf(&quot;&lt;p&gt;description: &quot; + n[&quot;description&quot;] + &quot;&lt;/p&gt;&quot;)
			fmt.Printf(&quot;&lt;p&gt;link to article: &quot; + n[&quot;link&quot;] + &quot;&lt;/p&gt;&quot;)
		}
	
	} else {
		fmt.Println(err)
	}
	
} else {
	fmt.Println(err)
}

and here's a small example of the get request response looks like

{
    &quot;stories&quot;: [{
        &quot;description&quot;: &quot;Despite the fact that shoppers descended upon stores after giving thanks, Black Friday wasn&#39;t without its share of brawls.&quot;,
        &quot;guid&quot;: [{
            &quot;isPermalink&quot;: &quot;true&quot;,
            &quot;value&quot;: &quot;http:\/\/apidata.usatoday.com\/story\/news\/nation-now\/2013\/11\/29\/black-friday-police-violence\/3783467\/?kjnd=Pvzhnh75%2BZ3dnzxHVv571HQOfzKReZECsSPCBGnAiXlbHijpqdc3TQoe4dYfzVlB-8d81f9e3-0b56-421e-a5da-121f9eb83de3_E50GPTZL1%2FYloJsxpxSnp8AhoO2O9prQtDTYiwN3sbV0SfQ5wriH1zooo6XgNPTr&quot;
        }],
        &quot;link&quot;: &quot;http:\/\/apidata.usatoday.com\/story\/news\/nation-now\/2013\/11\/29\/black-friday-police-violence\/3783467\/?kjnd=LOCSg6KVoQR3pwnZyGmcgcDZXwce0MwglPkURuQ%2BzMkUdNzQ2GXJr%2FPfLCl4Hf38-8d81f9e3-0b56-421e-a5da-121f9eb83de3_Zp5d44u%2F3U2IkXWRbNP0OwyXjRkEgShxoJC0wp7%2FOJoFPCI979Zw4qgNkWkOG1x1&quot;,
        &quot;pubDate&quot;: &quot;Fri, 29 Nov 2013 02:57:43 GMT&quot;,
        &quot;title&quot;: &quot;Black Friday frenzy leads to reports of violence&quot;
    }, {
        &quot;description&quot;: &quot;President Obama&#39;s law faces hurdles beyond the Supreme Court case on the birth control mandate.&quot;,
        &quot;guid&quot;: [{
            &quot;isPermalink&quot;: &quot;true&quot;,
            &quot;value&quot;: &quot;http:\/\/apidata.usatoday.com\/story\/news\/politics\/2013\/11\/29\/supreme-court-obamacare-lawsuits-irs\/3760811\/?kjnd=sCqadf244XkWTNcS0zAI%2Ba25XsnxwAX3ahu8NP0bzKdU4Kx31rJsa0cWlhvnwMl8-8d81f9e3-0b56-421e-a5da-121f9eb83de3_wtrtyHNPao7CqrB0IR7%2Bj3GFwJMhSYFSrOrrGZCkX2BStipIyyDtQoTLLFCGoLj0&quot;
        }],
        &quot;link&quot;: &quot;http:\/\/apidata.usatoday.com\/story\/news\/politics\/2013\/11\/29\/supreme-court-obamacare-lawsuits-irs\/3760811\/?kjnd=Be2GdDxc2cZdIOPiCpcL9vz%2FFvmT859xSGoVutxwurqJ%2FCwvTt8vjs2s9MHzI1hO-8d81f9e3-0b56-421e-a5da-121f9eb83de3_88mb%2BwbADj1MvtG9%2BiYMhVS43CRGBEVdn0v5QJsORviARUA3qR0iE9LBr7NpNrT7&quot;,
        &quot;pubDate&quot;: &quot;Fri, 29 Nov 2013 11:12:08 GMT&quot;,
        &quot;title&quot;: &quot;Long-shot legal challenges to health care law abound&quot;
    }
    }]
}

AND finally here's what the error looks like at runtime

panic: interface conversion: interface is map[string]interface {}, not map[string][]interface {}

not really sure how i should go about this, so anyone with pre-existing knowledge of working with RESTful api's in golang that would have some insight would be greatly appreciated!

答案1

得分: 2

抱歉之前的愚蠢评论,你提供的json格式不正确,所以我验证了json数据并提供了一个有效的示例,展示了如何解析和查询map。

byt := []byte(`{
    "stories": [
        {
            "description": "Despite the fact that shoppers descended upon stores after giving thanks, Black Friday wasn't without its share of brawls.",
            "guid": [
                {
                    "isPermalink": "true",
                    "value": "http://apidata.usatoday.com/story/news/nation-now/2013/11/29/black-friday-police-violence/3783467/?kjnd=Pvzhnh75%2BZ3dnzxHVv571HQOfzKReZECsSPCBGnAiXlbHijpqdc3TQoe4dYfzVlB-8d81f9e3-0b56-421e-a5da-121f9eb83de3_E50GPTZL1%2FYloJsxpxSnp8AhoO2O9prQtDTYiwN3sbV0SfQ5wriH1zooo6XgNPTr"
                }
            ],
            "link": "http://apidata.usatoday.com/story/news/nation-now/2013/11/29/black-friday-police-violence/3783467/?kjnd=LOCSg6KVoQR3pwnZyGmcgcDZXwce0MwglPkURuQ%2BzMkUdNzQ2GXJr%2FPfLCl4Hf38-8d81f9e3-0b56-421e-a5da-121f9eb83de3_Zp5d44u%2F3U2IkXWRbNP0OwyXjRkEgShxoJC0wp7%2FOJoFPCI979Zw4qgNkWkOG1x1",
            "pubDate": "Fri, 29 Nov 2013 02:57:43 GMT",
            "title": "Black Friday frenzy leads to reports of violence"
        },
        {
            "description": "President Obama's law faces hurdles beyond the Supreme Court case on the birth control mandate.",
            "guid": [
                {
                    "isPermalink": "true",
                    "value": "http://apidata.usatoday.com/story/news/politics/2013/11/29/supreme-court-obamacare-lawsuits-irs/3760811/?kjnd=sCqadf244XkWTNcS0zAI%2Ba25XsnxwAX3ahu8NP0bzKdU4Kx31rJsa0cWlhvnwMl8-8d81f9e3-0b56-421e-a5da-121f9eb83de3_wtrtyHNPao7CqrB0IR7%2Bj3GFwJMhSYFSrOrrGZCkX2BStipIyyDtQoTLLFCGoLj0"
                }
            ],
            "link": "http://apidata.usatoday.com/story/news/politics/2013/11/29/supreme-court-obamacare-lawsuits-irs/3760811/?kjnd=Be2GdDxc2cZdIOPiCpcL9vz%2FFvmT859xSGoVutxwurqJ%2FCwvTt8vjs2s9MHzI1hO-8d81f9e3-0b56-421e-a5da-121f9eb83de3_88mb%2BwbADj1MvtG9%2BiYMhVS43CRGBEVdn0v5QJsORviARUA3qR0iE9LBr7NpNrT7",
            "pubDate": "Fri, 29 Nov 2013 11:12:08 GMT",
            "title": "Long-shot legal challenges to health care law abound"
        }
    ]
}`)

var dat map[string][]map[string]interface{}

if err := json.Unmarshal(byt, &dat); err != nil {
    panic(err)
}

fmt.Println(dat["stories"][1]["description"])

上面的示例输出为:

President Obama的法律面临着超越最高法院关于避孕控制命令的案件的障碍。

编辑:添加了与你定义的map变量相同的定义。

编辑2:我调整了示例以展示更高级别的查询。这还需要对定义的map进行小的更改。

英文:

Apologies for the stupid comment earlier, the json you supplied was not valid so I validated the json payload and here is a working example of Unmarshalling + querying the map

byt := []byte(`{
    &quot;stories&quot;: [
        {
            &quot;description&quot;: &quot;Despite the fact that shoppers descended upon stores after giving thanks, Black Friday wasn&#39;t without its share of brawls.&quot;,
            &quot;guid&quot;: [
                {
                    &quot;isPermalink&quot;: &quot;true&quot;,
                    &quot;value&quot;: &quot;http://apidata.usatoday.com/story/news/nation-now/2013/11/29/black-friday-police-violence/3783467/?kjnd=Pvzhnh75%2BZ3dnzxHVv571HQOfzKReZECsSPCBGnAiXlbHijpqdc3TQoe4dYfzVlB-8d81f9e3-0b56-421e-a5da-121f9eb83de3_E50GPTZL1%2FYloJsxpxSnp8AhoO2O9prQtDTYiwN3sbV0SfQ5wriH1zooo6XgNPTr&quot;
                }
            ],
            &quot;link&quot;: &quot;http://apidata.usatoday.com/story/news/nation-now/2013/11/29/black-friday-police-violence/3783467/?kjnd=LOCSg6KVoQR3pwnZyGmcgcDZXwce0MwglPkURuQ%2BzMkUdNzQ2GXJr%2FPfLCl4Hf38-8d81f9e3-0b56-421e-a5da-121f9eb83de3_Zp5d44u%2F3U2IkXWRbNP0OwyXjRkEgShxoJC0wp7%2FOJoFPCI979Zw4qgNkWkOG1x1&quot;,
            &quot;pubDate&quot;: &quot;Fri, 29 Nov 2013 02:57:43 GMT&quot;,
            &quot;title&quot;: &quot;Black Friday frenzy leads to reports of violence&quot;
        },
        {
            &quot;description&quot;: &quot;President Obama&#39;s law faces hurdles beyond the Supreme Court case on the birth control mandate.&quot;,
            &quot;guid&quot;: [
                {
                    &quot;isPermalink&quot;: &quot;true&quot;,
                    &quot;value&quot;: &quot;http://apidata.usatoday.com/story/news/politics/2013/11/29/supreme-court-obamacare-lawsuits-irs/3760811/?kjnd=sCqadf244XkWTNcS0zAI%2Ba25XsnxwAX3ahu8NP0bzKdU4Kx31rJsa0cWlhvnwMl8-8d81f9e3-0b56-421e-a5da-121f9eb83de3_wtrtyHNPao7CqrB0IR7%2Bj3GFwJMhSYFSrOrrGZCkX2BStipIyyDtQoTLLFCGoLj0&quot;
                }
            ],
            &quot;link&quot;: &quot;http://apidata.usatoday.com/story/news/politics/2013/11/29/supreme-court-obamacare-lawsuits-irs/3760811/?kjnd=Be2GdDxc2cZdIOPiCpcL9vz%2FFvmT859xSGoVutxwurqJ%2FCwvTt8vjs2s9MHzI1hO-8d81f9e3-0b56-421e-a5da-121f9eb83de3_88mb%2BwbADj1MvtG9%2BiYMhVS43CRGBEVdn0v5QJsORviARUA3qR0iE9LBr7NpNrT7&quot;,
            &quot;pubDate&quot;: &quot;Fri, 29 Nov 2013 11:12:08 GMT&quot;,
            &quot;title&quot;: &quot;Long-shot legal challenges to health care law abound&quot;
        }
    ]
}`)

	var dat map[string][]map[string]interface{}

	if err := json.Unmarshal(byt, &amp;dat); err != nil {
		panic(err)
	}

	fmt.Println(dat[&quot;stories&quot;][1][&quot;description&quot;])

The above example prints:

> President Obama's law faces hurdles beyond the Supreme Court case on
> the birth control mandate.

Edit: added the same definition you have for map variable.

Edit 2: I've adjust the example to show higher levels of querying. Also this required a small change in the defined map.

答案2

得分: 2

我用一些与 JSON 对象匹配的结构来修复了它... 这有点麻烦。

如果有人想在 Golang 中使用这个 API,可以参考下面的代码:

type stories struct {
    Stories []story
}
type story struct {
    Description string
    Guid []guid
    Link string
    PubDate string
    Title string
}
type guid struct {
    IsPermalink string
    Value string
}

希望对你有帮助!

英文:

i ended up fixing it using some structures that matched the json objects... which was kind of a pain.

here it is if anyone ever wants to use this api in golang

type stories struct {
    Stories []story
}
type story struct {
    Description string
    Guid []guid
    Link string
    PubDate string
    Title string
}
type guid struct {
    IsPermalink string
    Value string
}

答案3

得分: 0

以下是使用我创建的结构的应用程序的最终函数的样子:

func newsHandler(w *odie.ResponseWriter, req *odie.Request, vars odie.Context) {
    var count = vars.Get("numResults")
    if (count == "") {
        count = "10"
    }
    // 向 API 发送请求
    resp, err := http.Get("http://api.usatoday.com/open/articles/topnews/home?count=" + count + "&days=0&page=0&encoding=json&api_key=myApiKey")
    
    if(err == nil){
        body, err := ioutil.ReadAll(resp.Body)
        if(err == nil) {
            var data stories
            err := json.Unmarshal(body, &data)

            if(err == nil) {
                for i:=0; i<len(data.Stories); i++ {
                    var article = data.Stories[i]
            
                    var link = strings.Split(article.Link,"apidata.")
                
                    fmt.Fprintf(w, "<h2>" + article.Title + "</h2>")
                    fmt.Fprintf(w, "<p>" + article.Description + "</p>")
                    if( len(link) > 1) {
                        fmt.Fprintf(w, "文章链接: <a rel='nofollow' href=" + link[0] + link[1] + ">" + link[0] + link[1] + "</a><br/><br/>")
                    } else {
                        fmt.Fprintf(w, "文章链接: <a rel='nofollow' href=" + link[0] + ">" + link[0] + "</a><br/><br/>")
                    }
                }           
            } else {
               fmt.Println(err)
            }
    
        } else {
            fmt.Println(err)
        }
    
    } else {
        fmt.Println(err)
    }
}

希望这可以帮到你!

英文:

just in case anyone was curious, this is what the final function for my app looked like using the structures i made:

func newsHandler(w *odie.ResponseWriter, req *odie.Request, vars odie.Context) {
var count = vars.Get(&quot;numResults&quot;)
if (count == &quot;&quot;) {
count = &quot;10&quot;
}
// get request to API
resp, err := http.Get(&quot;http://api.usatoday.com/open/articles/topnews/home?count=&quot; + count + &quot;&amp;days=0&amp;page=0&amp;encoding=json&amp;api_key=myApiKey&quot;)
if(err == nil){
body, err := ioutil.ReadAll(resp.Body)
if(err == nil) {
var data stories
err := json.Unmarshal(body, &amp;data)
if(err == nil) {
for i:=0; i&lt;len(data.Stories); i++ {
var article = data.Stories[i]
var link = strings.Split(article.Link,&quot;apidata.&quot;)
fmt.Fprintf(w, &quot;&lt;h2&gt;&quot; + article.Title + &quot;&lt;/h2&gt;&quot;)
fmt.Fprintf(w, &quot;&lt;p&gt;&quot; + article.Description + &quot;&lt;/p&gt;&quot;)
if( len(link) &gt; 1) {
fmt.Fprintf(w, &quot;link to article: &lt;a rel=&#39;nofollow&#39; href=&quot; + link[0] + link[1] + &quot;&gt;&quot; + link[0] + link[1] + &quot;&lt;/a&gt;&lt;br/&lt;br/&gt;&quot;)
} else {
fmt.Fprintf(w, &quot;link to article: &lt;a rel=&#39;nofollow&#39; href=&quot; + link[0] + &quot;&gt;&quot; + link[0] + &quot;&lt;/a&gt;&lt;br/&lt;br/&gt;&quot;)
}
}			
} else {
fmt.Println(err)
}
} else {
fmt.Println(err)
}
} else {
fmt.Println(err)
}
}

huangapple
  • 本文由 发表于 2013年11月30日 06:07:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/20293977.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定