Golang unmarshall JSON from api.nal.usda.gov/ndb

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

Golang unmarshall JSON from api.nal.usda.gov/ndb

问题

你好,我尝试将来自api.nal.usda.gov/ndb的JSON响应解组成结构体,但它总是返回空值:

{        []}

示例JSON:

{
    "list": {
        "q": "butter",
        "sr": "28",
        "ds": "any",
        "start": 0,
        "end": 50,
        "total": 4003,
        "group": "",
        "sort": "r",
        "item": [
            {
                "offset": 0,
                "group": "Branded Food Products Database",
                "name": "BLUE BUNNY, PEANUT BUTTER PANIC, ICE CREAM, POWERFUL PEANUT BUTTER ICE CREAM CHARGED WITH PEANUT BUTTER AND FUDGE SAUCES AND OVERLOADED WITH PEANUT BUTTER CUPS, UPC: 070640034086",
                "ndbno": "45011419",
                "ds": "BL"
            },
            {
                "offset": 1,
                "group": "Branded Food Products Database",
                "name": "BLUE BUNNY, ICE CREAM, PEANUT BUTTER PARTY, PEANUT BUTTER ICE CREAM, PEANUT BUTTER AND FUDGE SWIRLS, PEANUT BUTTER CUPS, UPC: 070640012411",
                "ndbno": "45110466",
                "ds": "BL"
            }
        ]
    }
}

我使用https://jsonformatter.curiousconcept.com/检查了JSON响应,它是正确的。希望你能告诉我为什么会出现这种情况,因为我对Golang还很陌生。

我的结构体定义如下:

type List struct {
    Q     string `json:"q,omitempty"`
    Sr    string `json:"sr,omitempty"`
    Ds    string `json:"ds,omitempty"`
    Start string `json:"start,omitempty"`
    End   string `json:"end,omitempty"`
    Total string `json:"total,omitempty"`
    Group string `json:"group,omitempty"`
    Sort  string `json:"sort,omitempty"`
    Item  []Item `json:"item,omitempty"`
}

type Item struct {
    Offset string `json:"offset,omitempty"`
    Group  string `json:"group,omitempty"` //food group to which the food belongs
    Name   string `json:"name,omitempty"`  //the food’s name
    Ndbno  string `json:"ndbno,omitempty"`  //the food’s NDB Number
    Ds     string `json:"ds,omitempty"`    //Data source: BL=Branded Food Products or SR=Standard Release
}

代码部分如下:

func (sr *SearchRequest) fetch() {

    url := "https://api.nal.usda.gov/ndb/search/?&" +
        "format=" + sr.format +
        "&q=" + sr.q +
        "&sort=" + sr.sort +
        "&max=" + strconv.FormatInt(sr.max, 10) +
        "&offset=" + strconv.FormatInt(sr.offset, 10) +
        "&api_key=" + sr.c.ApiKey

    r, err := http.Get(url)
    if err != nil {
        panic(err.Error())
    }
    defer r.Body.Close()

    b, err := ioutil.ReadAll(r.Body)
    if err != nil {
        panic(err.Error())
    }

    l := new(List)
    err = json.Unmarshal(b, &l)
    if err != nil {
        fmt.Println(err)
    }

    fmt.Println(l)

}
英文:

Hello I try to unmarshal the JSON response from api.nal.usda.gov/ndb into struct, but it always returns empty:

{        []}

Example JSON:

{
    "list": {
        "q": "butter",
        "sr": "28",
        "ds": "any",
        "start": 0,
        "end": 50,
        "total": 4003,
        "group": "",
        "sort": "r",
        "item": [
            {
                "offset": 0,
                "group": "Branded Food Products Database",
                "name": "BLUE BUNNY, PEANUT BUTTER PANIC, ICE CREAM, POWERFUL PEANUT BUTTER ICE CREAM CHARGED WITH PEANUT BUTTER AND FUDGE SAUCES AND OVERLOADED WITH PEANUT BUTTER CUPS, UPC: 070640034086",
                "ndbno": "45011419",
                "ds": "BL"
            },
            {
                "offset": 1,
                "group": "Branded Food Products Database",
                "name": "BLUE BUNNY, ICE CREAM, PEANUT BUTTER PARTY, PEANUT BUTTER ICE CREAM, PEANUT BUTTER AND FUDGE SWIRLS, PEANUT BUTTER CUPS, UPC: 070640012411",
                "ndbno": "45110466",
                "ds": "BL"
            }
        ]
    }
}

I checked the JSON response with https://jsonformatter.curiousconcept.com/, and it´s fine. I hope you can tell me why, since I am quite new to Golang.

My Structs:

type List struct {
	Q     string `json:"q,omitempty"`
	Sr    string `json:"sr,omitempty"`
	Ds    string `json:"ds,omitempty"`
	Start string `json:"start,omitempty"`
	End   string `json:"end,omitempty"`
	Total string `json:"total,omitempty"`
	Group string `json:"group,omitempty"`
	Sort  string `json:"sort,omitempty"`
	Item  []Item `json:"item,omitempty"`
}

type Item struct {
	Offset string `json:"offset,omitempty"`
	Group  string `json:"group,omitempty"` //food group to which the food belongs
	Name   string `json:"name,omitempty"`  //the food’s name
	Ndbno  string `json:"nbno,omitempty"`  //the food’s NDB Number
	Ds     string `json:"ds,omitempty"`    //Data source: BL=Branded Food Products or SR=Standard Release
}

Code:

func (sr *SearchRequest) fetch() {

    url := "https://api.nal.usda.gov/ndb/search/?" +
        "format=" + sr.format +
        "&q=" + sr.q +
        "&sort=" + sr.sort +
        "&max=" + strconv.FormatInt(sr.max, 10) +
        "&offset=" + strconv.FormatInt(sr.offset, 10) +
        "&api_key=" + sr.c.ApiKey

    r, err := http.Get(url)
    if err != nil {
        panic(err.Error())
    }
    defer r.Body.Close()

    b, err := ioutil.ReadAll(r.Body)
    if err != nil {
        panic(err.Error())
    }

    l := new(List)
    err = json.Unmarshal(b, &l)
    if err != nil {
        fmt.Println(err)
    }

    fmt.Println(l)

}

答案1

得分: 2

Go类型与JSON的结构不匹配。JSON中还有一个更深层次的对象。尝试使用以下代码:

var v struct {
    List List
}
err := json.Unmarshal([]byte(data), &v)

JSON中的一些字符串字段对应于数字。请使用数值类型(int、float64等)声明这些字段。

playground示例

英文:

The Go types do not match the structure of the JSON. There's one more level of objects in the JSON. Try this:

var v struct {
	List List
}
err := json.Unmarshal([]byte(data), &v)

Some of the string fields correspond to numbers in the JSON. Declare these fields with a numerical type (int, float64, ...).

playground example

答案2

得分: 0

IMHO你的结构与提供的JSON不匹配。请尝试以下代码:

package main

import (
	"encoding/json"
	"fmt"
)

type MyItem struct {
	Q     string `json:"q,omitempty"`
	Sr    string `json:"sr,omitempty"`
	Ds    string `json:"ds,omitempty"`
	Start int    `json:"start,omitempty"`
	End   int    `json:"end,omitempty"`
	Total int    `json:"total,omitempty"`
	Group string `json:"group,omitempty"`
	Sort  string `json:"sort,omitempty"`
	Item  []Item `json:"item,omitempty"`
}

type MyList struct {
	List MyItem `json:"list"`
}

type Item struct {
	Offset int    `json:"offset,omitempty"`
	Group  string `json:"group,omitempty"` // 食物所属的食物组
	Name   string `json:"name,omitempty"`  // 食物的名称
	Ndbno  string `json:"ndbno,omitempty"` // 食物的NDB编号
	Ds     string `json:"ds,omitempty"`    // 数据来源:BL=品牌食品产品或SR=标准发布
}

var jsonStr = `{
    "list": {
        "q": "butter",
        "sr": "28",
        "ds": "any",
        "start": 0,
        "end": 50,
        "total": 4003,
        "group": "",
        "sort": "r",
        "item": [
            {
                "offset": 0,
                "group": "Branded Food Products Database",
                "name": "BLUE BUNNY, PEANUT BUTTER PANIC, ICE CREAM, POWERFUL PEANUT BUTTER ICE CREAM CHARGED WITH PEANUT BUTTER AND FUDGE SAUCES AND OVERLOADED WITH PEANUT BUTTER CUPS, UPC: 070640034086",
                "ndbno": "45011419",
                "ds": "BL"
            },
            {
                "offset": 1,
                "group": "Branded Food Products Database",
                "name": "BLUE BUNNY, ICE CREAM, PEANUT BUTTER PARTY, PEANUT BUTTER ICE CREAM, PEANUT BUTTER AND FUDGE SWIRLS, PEANUT BUTTER CUPS, UPC: 070640012411",
                "ndbno": "45110466",
                "ds": "BL"
            }
        ]
    }
}`

func main() {
	b := jsonStr

	l := new(MyList)
	err := json.Unmarshal([]byte(b), &l)
	if err != nil {
		fmt.Println(err)
	}

	fmt.Println(l)
}

编辑:使用spew.Dump(l)打印结果可能不易阅读,因此这里提供使用spew.Dump(l)的结果(go get -u github.com/davecgh/go-spew/spew):

List: (main.MyItem) {
Q: (string) (len=6) "butter",
Sr: (string) (len=2) "28",
Ds: (string) (len=3) "any",
Start: (int) 0,
End: (int) 50,
Total: (int) 4003,
Group: (string) "",
Sort: (string) (len=1) "r",
Item: ([]main.Item) (len=2 cap=4) {
(main.Item) {
Offset: (int) 0,
Group: (string) (len=30) "Branded Food Products Database",
Name: (string) (len=178) "BLUE BUNNY, PEANUT BUTTER PANIC, ICE CREAM, POWERFUL PEANUT BUTTER ICE CREAM CHARGED WITH PEANUT BUTTER AND FUDGE SAUCES AND OVERLOADED WITH PEANUT BUTTER CUPS, UPC: 070640034086",
Ndbno: (string) "",
Ds: (string) (len=2) "BL"
},
(main.Item) {
Offset: (int) 1,
Group: (string) (len=30) "Branded Food Products Database",
Name: (string) (len=138) "BLUE BUNNY, ICE CREAM, PEANUT BUTTER PARTY, PEANUT BUTTER ICE CREAM, PEANUT BUTTER AND FUDGE SWIRLS, PEANUT BUTTER CUPS, UPC: 070640012411",
Ndbno: (string) "",
Ds: (string) (len=2) "BL"
}
}
}
英文:

IMHO your struct doesn't match to JSON you provided. Try:

package main
import (
"encoding/json"
"fmt"
)
type MyItem struct {
Q     string `json:"q,omitempty"`
Sr    string `json:"sr,omitempty"`
Ds    string `json:"ds,omitempty"`
Start int `json:"start,omitempty"`
End   int `json:"end,omitempty"`
Total int `json:"total,omitempty"`
Group string `json:"group,omitempty"`
Sort  string `json:"sort,omitempty"`
Item  []Item `json:"item,omitempty"`
}
type MyList struct {
List MyItem `json:"list"`
}
type Item struct {
Offset int `json:"offset,omitempty"`
Group  string `json:"group,omitempty"` //food group to which the food belongs
Name   string `json:"name,omitempty"`  //the food’s name
Ndbno  string `json:"nbno,omitempty"`  //the food’s NDB Number
Ds     string `json:"ds,omitempty"`    //Data source: BL=Branded Food Products or SR=Standard Release
}
var jsonStr = `{
"list": {
"q": "butter",
"sr": "28",
"ds": "any",
"start": 0,
"end": 50,
"total": 4003,
"group": "",
"sort": "r",
"item": [
{
"offset": 0,
"group": "Branded Food Products Database",
"name": "BLUE BUNNY, PEANUT BUTTER PANIC, ICE CREAM, POWERFUL PEANUT BUTTER ICE CREAM CHARGED WITH PEANUT BUTTER AND FUDGE SAUCES AND OVERLOADED WITH PEANUT BUTTER CUPS, UPC: 070640034086",
"ndbno": "45011419",
"ds": "BL"
},
{
"offset": 1,
"group": "Branded Food Products Database",
"name": "BLUE BUNNY, ICE CREAM, PEANUT BUTTER PARTY, PEANUT BUTTER ICE CREAM, PEANUT BUTTER AND FUDGE SWIRLS, PEANUT BUTTER CUPS, UPC: 070640012411",
"ndbno": "45110466",
"ds": "BL"
}]
}
}`
func main() {
b := jsonStr
l := new(MyList)
err := json.Unmarshal([]byte(b), &l)
if err != nil {
fmt.Println(err)
}
fmt.Println(l)
}

EDIT: It is hard to read result of println or printf with %+v so here is the result with spew.Dump(l) (go get -u github.com/davecgh/go-spew/spew):

List: (main.MyItem) {
Q: (string) (len=6) "butter",
Sr: (string) (len=2) "28",
Ds: (string) (len=3) "any",
Start: (int) 0,
End: (int) 50,
Total: (int) 4003,
Group: (string) "",
Sort: (string) (len=1) "r",
Item: ([]main.Item) (len=2 cap=4) {
(main.Item) {
Offset: (int) 0,
Group: (string) (len=30) "Branded Food Products Database",
Name: (string) (len=178) "BLUE BUNNY, PEANUT BUTTER PANIC, ICE CREAM, POWERFUL PEANUT BUTTER ICE CREAM CHARGED WITH PEANUT BUTTER AND FUDGE SAUCES AND OVERLOADED WITH PEANUT BUTTER CUPS, UPC: 070640034086",
Ndbno: (string) "",
Ds: (string) (len=2) "BL"
},
(main.Item) {
Offset: (int) 1,
Group: (string) (len=30) "Branded Food Products Database",
Name: (string) (len=138) "BLUE BUNNY, ICE CREAM, PEANUT BUTTER PARTY, PEANUT BUTTER ICE CREAM, PEANUT BUTTER AND FUDGE SWIRLS, PEANUT BUTTER CUPS, UPC: 070640012411",
Ndbno: (string) "",
Ds: (string) (len=2) "BL"
}
}
}
})

huangapple
  • 本文由 发表于 2017年4月11日 23:02:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/43349648.html
匿名

发表评论

匿名网友

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

确定