doujing5846
2016-05-11 02:27
浏览 783
已采纳

在golang json.Unmarshal中处理单个或数组结构的好方法是什么?

I am building a stock quote web app by using Go and Yahoo API.

The question is how to switch between array and single struct without writing another struct. I am not sure how to explain it in words. Here is the example:

Get one symbol quote from Yahoo API looks like this:

{"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%"}}}}

Get multiple quotes from 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%"}]}}}

The difference is the quote becomes an array [].

How to handle it when using json.Unmarshal(quoteResultRawJSON, &queryResult)?

I have struct look like:

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"`
 }

Do I have to write another struct to handle array?

  • 写回答
  • 好问题 提建议
  • 追加酬金
  • 关注问题
  • 邀请回答

1条回答 默认 最新

  • doucheng3407 2016-05-11 03:03
    最佳回答

    control the unmarshal process with UnmarshalJSON() override.

    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)
    }
    
    评论
    解决 无用
    打赏 举报

相关推荐 更多相似问题