dsnrixf6765 2017-06-20 10:13
浏览 40

解组动态JSON [重复]

This question already has an answer here:

I receive dynamic JSON from an API that follows this pattern:

{
    "ts": timestamp,
    "data": [
        [ code1, payload1 ],
        [ code2, payload2 ],
        ...
    ]
}

For example the raw data will be:

    var streamSnapshot = []byte(

`{ 
   "ts": 1496244373.04,
   "data":[
      ["xrate", {"rate":1.2916,"ccy":"USD"}],
      ["balance", 
         {
            "open_stake":["GBP", 0.0],
            "balance":["GBP", 0.0]
         }
      ],
      ["event", 
         {
            "competition_id":"545",
            "ir_status":"pre_event",
            "start_time":"2017-09-10T17:00:00+00:00",
            "competition_name":"USA NFL",
            "event_id":"2017-09-10,21617,21635",
            "home":"Buffalo Bills",
            "away":"New York Jets",
            "sport":"af",
            "competition_country":"US"
         }
      ],
      ["sync", {"Token":"eb1c57132d004f8d8fb967c076921fac"}]
   ]
}`)

Considering that we want to avoid unmarshalling to a struct like this:

type StreamMessage struct {
    Data [][]interface{} `json:"data"`
    Ts   float64         `json:"ts"`
} 

where we would have to cast the data back like:

    m := raw.(map[string]interface{})

    switch messageType {
    case XRATE:
        xrate := XRate{
            Message: Message{
                Type:      XRATE,
                TimeStamp: msg.Ts,
            },
            rate: m["rate"].(float64),
            ccy:  m["ccy"].(string),
        }  
     ...

What would be the better way of unmarshalling this?

</div>
  • 写回答

1条回答 默认 最新

  • dqk77945 2017-06-20 11:03
    关注
    package main
    
    import (
        "bytes"
        "encoding/json"
        "errors"
        "fmt"
    )
    
    type StreamMessage struct {
        Data []*Data `json:"data"`
        Ts   float64 `json:"ts"`
    }
    
    type Data struct {
        Type    string
        XRate   *XRateData
        Balance *BalanceData
        Event   *EventData
        Sync    *SyncData
    }
    
    func (d *Data) UnmarshalJSON(b []byte) error {
        dec := json.NewDecoder(bytes.NewReader(b))
        t, _ := dec.Token()
        if delim, ok := t.(json.Delim); !ok || delim != '[' {
            return errors.New("expecting data to be an array")
        }
    
        if err := dec.Decode(&d.Type); err != nil {
            return err
        }
    
        var err error
        switch d.Type {
        case "xrate":
            err = dec.Decode(&d.XRate)
        case "sync":
            err = dec.Decode(&d.Sync)
        case "balance":
            err = dec.Decode(&d.Balance)
        case "event":
            err = dec.Decode(&d.Event)
        default:
            return errors.New("unknown data type " + d.Type)
        }
    
        if err != nil {
            return err
        }
    
        t, _ = dec.Token()
        if delim, ok := t.(json.Delim); !ok || delim != ']' {
            return errors.New("expecting array to be two elements")
        }
    
        return nil
    }
    
    type XRateData struct {
        Rate json.Number `json:"rate"`
        CCY  string      `json:"ccy"`
    }
    
    type BalanceData struct {
        // TODO
    }
    
    type EventData struct {
        // TODO
    }
    
    type SyncData struct {
        Token string `json:"Token"`
    }
    
    var streamSnapshot = []byte(
    
        `{ 
       "ts": 1496244373.04,
       "data":[
          ["xrate", {"rate":1.2916,"ccy":"USD"}],
          ["balance", 
             {
                "open_stake":["GBP", 0.0],
                "balance":["GBP", 0.0]
             }
          ],
          ["event", 
             {
                "competition_id":"545",
                "ir_status":"pre_event",
                "start_time":"2017-09-10T17:00:00+00:00",
                "competition_name":"USA NFL",
                "event_id":"2017-09-10,21617,21635",
                "home":"Buffalo Bills",
                "away":"New York Jets",
                "sport":"af",
                "competition_country":"US"
             }
          ],
          ["sync", {"Token":"eb1c57132d004f8d8fb967c076921fac"}]
       ]
    }`)
    
    func main() {
        var sm StreamMessage
        if err := json.Unmarshal(streamSnapshot, &sm); err != nil {
            panic(err)
        }
        fmt.Println(sm)
    }
    

    https://play.golang.org/p/ktABS6z40m

    评论

报告相同问题?

悬赏问题

  • ¥15 基于PLC的三轴机械手程序
  • ¥15 多址通信方式的抗噪声性能和系统容量对比
  • ¥15 winform的chart曲线生成时有凸起
  • ¥15 msix packaging tool打包问题
  • ¥15 finalshell节点的搭建代码和那个端口代码教程
  • ¥15 Centos / PETSc / PETGEM
  • ¥15 centos7.9 IPv6端口telnet和端口监控问题
  • ¥20 完全没有学习过GAN,看了CSDN的一篇文章,里面有代码但是完全不知道如何操作
  • ¥15 使用ue5插件narrative时如何切换关卡也保存叙事任务记录
  • ¥20 海浪数据 南海地区海况数据,波浪数据