在 golang json.Unmarshal 中处理单个或数组结构的好方法是什么?
What is a good way to handle single or array struct in golang json.Unmarshal?
我正在使用 Go 和 Yahoo API 构建股票报价 Web 应用程序。
问题是如何在不编写另一个结构的情况下在数组和单个结构之间切换。我不确定如何用语言来解释它。
这是示例:
从雅虎获取一个符号引用 API 如下所示:
{"query":{"count":1,"created":"2016-05-11T02:12:33Z","lang":"en-US","results":{"quote":{"Change":"+0.21","DaysLow":"9.32","DaysHigh":"9.68","Name":"Alcoa Inc. Common Stock","Open":"9.56","PreviousClose":"9.46","Symbol":"aa","Volume":"22266533","PercentChange":"+2.22%"}}}}
从 Yahoo 获取多个引用 API:
{"query":{"count":2,"created":"2016-05-11T02:17:48Z","lang":"en-us","results":{"quote":[{"Change":"+0.21","DaysLow":"9.32","DaysHigh":"9.68","Name":"Alcoa Inc. Common Stock","Open":"9.56","PreviousClose":"9.46","Symbol":"aa","Volume":"22266533","PercentChange":"+2.22%"},{"Change":"+0.63","DaysLow":"92.11","DaysHigh":"93.57","Name":"Apple Inc.","Open":"93.35","PreviousClose":"92.79","Symbol":"aapl","Volume":"33686836","PercentChange":"+0.68%"}]}}}
区别在于引号变成了一个数组[]
。
使用json.Unmarshal(quoteResultRawJSON, &queryResult)
时如何处理?
我的结构如下:
type QueryResult struct {
Id bson.ObjectId `bson:"_id,omitempty"`
Query Query `json:"query"`
}
type Query struct {
Count int `json:"count"`
Created string `json:"created"`
Lang string `json:"lang"`
Results Quote `json:"results"`
}
type Quote struct {
Quote StockQuote `json:"quote"` //Here is the difference. Do I need to re-write the whole struct in order to handle []
}
type StockQuote struct {
Change string `json:"change"`
PercentChange string `json:"percentChange"`
DaysLow string `json:"daysLow"`
DaysHigh string `json:"daysHigh"`
Open string `json:"open"`
PreviousClose string `json:"previousClose"`
Symbol string `json:"symbol"`
Name string `json:"name"`
Volume string `json:"volume"`
}
我是否必须编写另一个结构来处理数组?
使用 UnmarshalJSON()
覆盖控制解组过程。
https://play.golang.org/p/pCSgymQYC3
package main
import (
"log"
"encoding/json"
"bytes"
)
const(
s1=`{"query":{"count":1,"created":"2016-05-11T02:12:33Z","lang":"en-US","results":{"quote":{"Change":"+0.21","DaysLow":"9.32","DaysHigh":"9.68","Name":"Alcoa Inc. Common Stock","Open":"9.56","PreviousClose":"9.46","Symbol":"aa","Volume":"22266533","PercentChange":"+2.22%"}}}}`
s2=`{"query":{"count":2,"created":"2016-05-11T02:17:48Z","lang":"en-us","results":{"quote":[{"Change":"+0.21","DaysLow":"9.32","DaysHigh":"9.68","Name":"Alcoa Inc. Common Stock","Open":"9.56","PreviousClose":"9.46","Symbol":"aa","Volume":"22266533","PercentChange":"+2.22%"},{"Change":"+0.63","DaysLow":"92.11","DaysHigh":"93.57","Name":"Apple Inc.","Open":"93.35","PreviousClose":"92.79","Symbol":"aapl","Volume":"33686836","PercentChange":"+0.68%"}]}}}`
)
type QueryResult struct {
//Id bson.ObjectId `bson:"_id,omitempty"`
Query Query `json:"query"`
}
type Query struct {
Count int `json:"count"`
Created string `json:"created"`
Lang string `json:"lang"`
Results Quote `json:"results"`
}
type structOrArray struct{
parent *Quote
s StockQuote
a []StockQuote
}
func (this *structOrArray)UnmarshalJSON(data []byte) error{
d := json.NewDecoder(bytes.NewBuffer(data))
t, err := d.Token();
if err != nil{
return err
}
if t==json.Delim('['){
if err := json.Unmarshal(data, &this.a);err != nil {
return err
}
return nil
}
if err := json.Unmarshal(data, &this.s);err != nil {
return err
}
return nil
}
type fakeQuote struct{
Load structOrArray `json:"quote"` //Here is the difference. Do I need to re-write the whole struct in order to handle []
}
type Quote struct {
Quote *StockQuote
Quotes []StockQuote
}
func (this *Quote)UnmarshalJSON(data []byte) error{
fq := fakeQuote{}
if err := json.Unmarshal(data, &fq);err != nil{
return err
}
this.Quote = &fq.Load.s
this.Quotes = fq.Load.a
return nil
}
type StockQuote struct {
Change string `json:"change"`
PercentChange string `json:"percentChange"`
DaysLow string `json:"daysLow"`
DaysHigh string `json:"daysHigh"`
Open string `json:"open"`
PreviousClose string `json:"previousClose"`
Symbol string `json:"symbol"`
Name string `json:"name"`
Volume string `json:"volume"`
}
func main() {
r := QueryResult{}
err := json.Unmarshal([]byte(s1), &r)
if err != nil {
log.Fatalln(err)
}
log.Println(r.Query.Results.Quote)
log.Println(r.Query.Results.Quotes)
err = json.Unmarshal([]byte(s2), &r)
if err != nil {
log.Fatalln(err)
}
log.Println(r.Query.Results.Quote)
log.Println(r.Query.Results.Quotes)
}
我正在使用 Go 和 Yahoo API 构建股票报价 Web 应用程序。
问题是如何在不编写另一个结构的情况下在数组和单个结构之间切换。我不确定如何用语言来解释它。 这是示例:
从雅虎获取一个符号引用 API 如下所示:
{"query":{"count":1,"created":"2016-05-11T02:12:33Z","lang":"en-US","results":{"quote":{"Change":"+0.21","DaysLow":"9.32","DaysHigh":"9.68","Name":"Alcoa Inc. Common Stock","Open":"9.56","PreviousClose":"9.46","Symbol":"aa","Volume":"22266533","PercentChange":"+2.22%"}}}}
从 Yahoo 获取多个引用 API:
{"query":{"count":2,"created":"2016-05-11T02:17:48Z","lang":"en-us","results":{"quote":[{"Change":"+0.21","DaysLow":"9.32","DaysHigh":"9.68","Name":"Alcoa Inc. Common Stock","Open":"9.56","PreviousClose":"9.46","Symbol":"aa","Volume":"22266533","PercentChange":"+2.22%"},{"Change":"+0.63","DaysLow":"92.11","DaysHigh":"93.57","Name":"Apple Inc.","Open":"93.35","PreviousClose":"92.79","Symbol":"aapl","Volume":"33686836","PercentChange":"+0.68%"}]}}}
区别在于引号变成了一个数组[]
。
使用json.Unmarshal(quoteResultRawJSON, &queryResult)
时如何处理?
我的结构如下:
type QueryResult struct {
Id bson.ObjectId `bson:"_id,omitempty"`
Query Query `json:"query"`
}
type Query struct {
Count int `json:"count"`
Created string `json:"created"`
Lang string `json:"lang"`
Results Quote `json:"results"`
}
type Quote struct {
Quote StockQuote `json:"quote"` //Here is the difference. Do I need to re-write the whole struct in order to handle []
}
type StockQuote struct {
Change string `json:"change"`
PercentChange string `json:"percentChange"`
DaysLow string `json:"daysLow"`
DaysHigh string `json:"daysHigh"`
Open string `json:"open"`
PreviousClose string `json:"previousClose"`
Symbol string `json:"symbol"`
Name string `json:"name"`
Volume string `json:"volume"`
}
我是否必须编写另一个结构来处理数组?
使用 UnmarshalJSON()
覆盖控制解组过程。
https://play.golang.org/p/pCSgymQYC3
package main
import (
"log"
"encoding/json"
"bytes"
)
const(
s1=`{"query":{"count":1,"created":"2016-05-11T02:12:33Z","lang":"en-US","results":{"quote":{"Change":"+0.21","DaysLow":"9.32","DaysHigh":"9.68","Name":"Alcoa Inc. Common Stock","Open":"9.56","PreviousClose":"9.46","Symbol":"aa","Volume":"22266533","PercentChange":"+2.22%"}}}}`
s2=`{"query":{"count":2,"created":"2016-05-11T02:17:48Z","lang":"en-us","results":{"quote":[{"Change":"+0.21","DaysLow":"9.32","DaysHigh":"9.68","Name":"Alcoa Inc. Common Stock","Open":"9.56","PreviousClose":"9.46","Symbol":"aa","Volume":"22266533","PercentChange":"+2.22%"},{"Change":"+0.63","DaysLow":"92.11","DaysHigh":"93.57","Name":"Apple Inc.","Open":"93.35","PreviousClose":"92.79","Symbol":"aapl","Volume":"33686836","PercentChange":"+0.68%"}]}}}`
)
type QueryResult struct {
//Id bson.ObjectId `bson:"_id,omitempty"`
Query Query `json:"query"`
}
type Query struct {
Count int `json:"count"`
Created string `json:"created"`
Lang string `json:"lang"`
Results Quote `json:"results"`
}
type structOrArray struct{
parent *Quote
s StockQuote
a []StockQuote
}
func (this *structOrArray)UnmarshalJSON(data []byte) error{
d := json.NewDecoder(bytes.NewBuffer(data))
t, err := d.Token();
if err != nil{
return err
}
if t==json.Delim('['){
if err := json.Unmarshal(data, &this.a);err != nil {
return err
}
return nil
}
if err := json.Unmarshal(data, &this.s);err != nil {
return err
}
return nil
}
type fakeQuote struct{
Load structOrArray `json:"quote"` //Here is the difference. Do I need to re-write the whole struct in order to handle []
}
type Quote struct {
Quote *StockQuote
Quotes []StockQuote
}
func (this *Quote)UnmarshalJSON(data []byte) error{
fq := fakeQuote{}
if err := json.Unmarshal(data, &fq);err != nil{
return err
}
this.Quote = &fq.Load.s
this.Quotes = fq.Load.a
return nil
}
type StockQuote struct {
Change string `json:"change"`
PercentChange string `json:"percentChange"`
DaysLow string `json:"daysLow"`
DaysHigh string `json:"daysHigh"`
Open string `json:"open"`
PreviousClose string `json:"previousClose"`
Symbol string `json:"symbol"`
Name string `json:"name"`
Volume string `json:"volume"`
}
func main() {
r := QueryResult{}
err := json.Unmarshal([]byte(s1), &r)
if err != nil {
log.Fatalln(err)
}
log.Println(r.Query.Results.Quote)
log.Println(r.Query.Results.Quotes)
err = json.Unmarshal([]byte(s2), &r)
if err != nil {
log.Fatalln(err)
}
log.Println(r.Query.Results.Quote)
log.Println(r.Query.Results.Quotes)
}