Go decode json string

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

Go decode json string

问题

发现在Go语言中解析JSON是一件非常麻烦的事情,请帮忙解决一下。这是我的JSON数据:

{
   "BTC_BCN":{
      "id":7,
      "last":"0.00000156",
      "lowestAsk":"0.00000156",
      "highestBid":"0.00000155",
      "percentChange":"0.01960784",
      "baseVolume":"4920.84786257",
      "quoteVolume":"3016048494.19305944",
      "isFrozen":"0",
      "high24hr":"0.00000183",
      "low24hr":"0.00000145"
   },
   "BTC_BELA":{
      "id":8,
      "last":"0.00008847",
      "lowestAsk":"0.00008848",
      "highestBid":"0.00008847",
      "percentChange":"-0.00405268",
      "baseVolume":"169.66498061",
      "quoteVolume":"1981232.44495809",
      "isFrozen":"0",
      "high24hr":"0.00008995",
      "low24hr":"0.00008120"
   },
   ...
}

我需要将其放入我创建的类型中:

// Crypto 是货币对象
type Crypto struct {
	iso           string // 这是键(例如:BTC_BCN)
	id            int
	last          float64
	lowestAsk     float64
	highestBid    float64
	percentChange float64
	baseVolume    float64
	quoteVolume   float64
	isFrozen      int
	high24hr      float64
	low24hr       float64
}

这是我目前的代码,但结果是键的位置是正确的,但值为空:

func main() {
	currencies := getCurrencies()
	if currencies == nil {
		return
	}
	fmt.Println(len(currencies))
}

func getCurrencies() map[string]Crypto {
	curList := make(map[string]Crypto)
	resp, err := http.Get("https://poloniex.com/public?command=returnTicker")
	if err != nil {
		sendEmail("Error getting data from poloniex " + err.Error())
		return nil
	}
	body, readErr := ioutil.ReadAll(resp.Body)
	reader := strings.NewReader(string(body))
	jsonErr := json.NewDecoder(reader).Decode(&curList)
	if readErr != nil {
		fmt.Printf("readErr: %s\n", readErr.Error())
	}
	if jsonErr != nil {
		fmt.Printf("jsonErr: %s\n", jsonErr.Error())
	}
	for k, v := range curList {
		fmt.Println("k:", k, "v:", v)
	}
	defer resp.Body.Close()
	return curList
}

输出结果为:

k: BTC_MAID v: {0 0 0 0 0 0 0 0 0 0}
k: BTC_NOTE v: {0 0 0 0 0 0 0 0 0 0}
k: BTC_VRC v: {0 0 0 0 0 0 0 0 0 0}
k: BTC_DOGE v: {0 0 0 0 0 0 0 0 0 0}...

请原谅我这个愚蠢的问题,但我已经花了几天时间,我觉得我漏掉了什么。谢谢。

英文:

discovered that go json decoding is a big pain in the butt so please help.
Here's my json:

 {  
   "BTC_BCN":{  
      "id":7,
      "last":"0.00000156",
      "lowestAsk":"0.00000156",
      "highestBid":"0.00000155",
      "percentChange":"0.01960784",
      "baseVolume":"4920.84786257",
      "quoteVolume":"3016048494.19305944",
      "isFrozen":"0",
      "high24hr":"0.00000183",
      "low24hr":"0.00000145"
   },
   "BTC_BELA":{  
      "id":8,
      "last":"0.00008847",
      "lowestAsk":"0.00008848",
      "highestBid":"0.00008847",
      "percentChange":"-0.00405268",
      "baseVolume":"169.66498061",
      "quoteVolume":"1981232.44495809",
      "isFrozen":"0",
      "high24hr":"0.00008995",
      "low24hr":"0.00008120"
   }, ...
}

So I need to put that in a type that I created

//Crypto is the currency object
type Crypto struct {
	iso           string //this is the key (ex: BTC_BCN)
	id            int
	last          float64
	lowestAsk     float64
	highestBid    float64
	percentChange float64
	baseVolume    float64
	quoteVolume   float64
	isFrozen      int
	high24hr      float64
	low24hr       float64
}

and here is what I did so far, but I ended up with the keys in place and an empty value

func main() {
	// sendEmail("Some text")
	currencies := getCurrencies()
	if currencies == nil {
		return
	}
	fmt.Println(len(currencies))

}

func getCurrencies() map[string]Crypto {
	curList := make(map[string]Crypto)
	resp, err := http.Get("https://poloniex.com/public?command=returnTicker")
	// fmt.Println(err)
	if err != nil {
		sendEmail("Error getting data from poloniex " + err.Error())
		return nil
	}
	body, readErr := ioutil.ReadAll(resp.Body)
	reader := strings.NewReader(string(body))
	jsonErr := json.NewDecoder(reader).Decode(&curList)
	// fmt.Printf("curList is : %#v\n", curList)
	// fmt.Printf("body is : %s\n", string(body))
	if readErr != nil {
		fmt.Printf("readErr: %s\n", readErr.Error())
	}
	if jsonErr != nil {
		fmt.Printf("jsonErr: %s\n", jsonErr.Error())
	}
	for k, v := range curList {
		fmt.Println("k:", k, "v:", v)
	}
	defer resp.Body.Close()
	return curList
}

output:

k: BTC_MAID v: {0 0 0 0 0 0 0 0 0 0}
k: BTC_NOTE v: {0 0 0 0 0 0 0 0 0 0}
k: BTC_VRC v: {0 0 0 0 0 0 0 0 0 0}
k: BTC_DOGE v: {0 0 0 0 0 0 0 0 0 0}...

Please excuse my stupid question but I've spent days on it and I think I am missing something.
Cheers.

答案1

得分: 2

//加密货币是货币对象
type Crypto struct {
Iso string //这是键(例如:BTC_BCN)
Id int
Last string
LowestAsk string
HighestBid string
PercentChange string
BaseVolume string
QuoteVolume string
IsFrozen int
High24hr string
Low24hr string
}

你需要通过将首字母大写来导出字段。此外,你的float64数据是以string类型表示的,因此你可以将其读取为字符串或在分配给Crypto对象之前进行格式化。


更新:

如@skomp所指出,你可以使用标签来注释从JSON文件中接收到的类型。

type Crypto struct {
CryptoKey
Id int
Last float64 json:"last,string"
LowestAsk float64 json:"lowestAsk,string"
HighestBid float64 json:"highestBid,string"
PercentChange float64 json:"percentChange,string"
BaseVolume float64 json:"baseVolume,string"
QuoteVolume float64 json:"quoteVolume,string"
IsFrozen int
High24hr float64 json:"high24hr,string"
Low24hr float64 json:"low24hr,string"
}

英文:
//Crypto is the currency object
type Crypto struct {
	Iso           string //this is the key (ex: BTC_BCN)
	Id            int
	Last          string
	LowestAsk     string
	HighestBid    string
	PercentChange string
	BaseVolume    string
	QuoteVolume   string
	IsFrozen      int
	High24hr      string
	Low24hr       string
}

You need to to export the fields by capitalising first character. On top of that, your float64 datas are in type: string,hence either you read as string or format before assign to object Crypto.


Updated:

As pointed by @skomp, you may use a tag to annotate the type you're receiving from json file.

type Crypto struct {
	CryptoKey
	Id            int
	Last          float64 `json:"last,string"`
	LowestAsk     float64 `json:"lowestAsk,string"`
	HighestBid    float64 `json:"highestBid,string"`
	PercentChange float64 `json:"percentChange,string"`
	BaseVolume    float64 `json:"baseVolume,string"`
	QuoteVolume   float64 `json:"quoteVolume,string"`
	IsFrozen      int
	High24hr      float64 `json:"high24hr,string"`
	Low24hr       float64 `json:"low24hr,string"`
}

答案2

得分: 1

你正在尝试将其解码为包含加密对象的映射。这是不正确的。请在结构定义中创建映射,如下所示:

type Crypto struct {
    iso   string  `json:"BTC_BCN"` // 这是键(例如:BTC_BCN)
    id    int     `json:"id"`
    last  float64 `json:"las"`
    ...
}

crypto := &Crypto{}
err = json.NewDecoder(reader).Decode(crypto)
英文:

You are trying to decode in to a map containing your crypto object. This is incorrect. Create the mappings in the struct definition like so:

type Crypto struct {
    iso           string  `json:"BTC_BCN"` //this is the key (ex: BTC_BCN)
    id            int     `json:"id"`
    last          float64 `json:"las"`
    ...
}

crypto := &Crypto{}
err = json.NewDecoder(reader).Decode(crypto)

huangapple
  • 本文由 发表于 2017年6月5日 12:41:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/44361778.html
匿名

发表评论

匿名网友

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

确定