Unmarshaling map in Go

Issue

I thought I understood unmarshalling by now, but I guess not. I’m having a little bit of trouble unmarshalling a map in go. Here is the code that I have so far

type OHLC_RESS struct {
    Pair map[string][]Candles
    Last int64 `json:"last"`
}

type Candles struct {
    Time   uint64
    Open   string
    High   string
    Low    string
    Close  string
    VWAP   string
    Volume string
    Count  int
}

func (c *Candles) UnmarshalJSON(d []byte) error {
    tmp := []interface{}{&c.Time, &c.Open, &c.High, &c.Low, &c.Close, &c.VWAP, &c.Volume, &c.Count}
    length := len(tmp)
    err := json.Unmarshal(d, &tmp)
    if err != nil {
        return err
    }
    g := len(tmp)
    if g != length {
        return fmt.Errorf("Lengths don't match: %d != %d", g, length)
    }
    return nil
}

func main() {
    response := []byte(`{"XXBTZUSD":[[1616662740,"52591.9","52599.9","52591.8","52599.9","52599.1","0.11091626",5],[1616662740,"52591.9","52599.9","52591.8","52599.9","52599.1","0.11091626",5]],"last":15}`)
    var resp OHLC_RESS
    err := json.Unmarshal(response, &resp)
    fmt.Println("resp: ", resp)
}

after running the code, the last field will unmarshal fine, but for whatever reason, the map is left without any value. Any help?

Solution

func (r *OHLC_RESS) UnmarshalJSON(d []byte) error {
    var m map[string]json.RawMessage
    if err := json.Unmarshal(d, &m); err != nil {
        return err
    }
    if last, ok := m["last"]; ok {
        if err := json.Unmarshal(last, &r.Last); err != nil {
            return err
        }
        delete(m, "last")
    }
    r.Pair = make(map[string][]Candles, len(m))
    for k, v := range m {
        cc := []Candles{}
        if err := json.Unmarshal(v, &cc); err != nil {
            return err
        }
        r.Pair[k] = cc
    }
    return nil
}

https://go.dev/play/p/Lj8a8Gx9fWH

Answered By – mkopriva

Answer Checked By – Senaida (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.