I\'m retrieving JSON from a third party website (home electricity usage), and depending on what I\'ve requested from the site, the JSON returned may or may not be an array.
Usually, whenever you have a JSON value of unknown type, you will use json.RawMessage to get it, peek into it, and unmarshal it correctly into the corresponding type. A simplified example:
// The A here can be either an object, or a JSON array of objects.
type Response struct {
RawAWrapper struct {
RawA json.RawMessage `json:"a"`
}
A A `json:"-"`
As []A `json:"-"`
}
type A struct {
B string
}
func (r *Response) UnmarshalJSON(b []byte) error {
if err := json.Unmarshal(b, &r.RawAWrapper); err != nil {
return err
}
if r.RawAWrapper.RawA[0] == '[' {
return json.Unmarshal(r.RawAWrapper.RawA, &r.As)
}
return json.Unmarshal(r.RawAWrapper.RawA, &r.A)
}
Playground: http://play.golang.org/p/2d_OrGltDu.
Guessing the content based on the first byte doesn't seem too robust to me though. Usually you'll have some sort of a clue in your JSON (like a length
or type
field on the same level as the dynamic one) that tells you whether you have an object or an array.
See also:
You can try to make custom json unmarshal method, like
func (a *GwrcmCustom) UnmarshalJSON(b []byte) (err error) {
g, ga := Gwrcmd{}, []Gwrcmd{}
if err = json.Unmarshal(b, &g); err == nil {
*a = make([]Gwrcmd, 1)
[]Gwrcmd(*a)[0] = Gwrcmd(g)
return
}
if err = json.Unmarshal(b, &ga); err == nil {
*a = GwrcmCustom(ga)
return
}
return
}
GwrcmCustom
is a custom type, slice of Gwrcm
type GwrcmCustom []Gwrcmd
So we will get slice always
Try this on Go playground
I hope this will help