Unmarshalling a JSON that may or may not return an array?

后端 未结 2 765
爱一瞬间的悲伤
爱一瞬间的悲伤 2020-12-06 19:33

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.

2条回答
  •  囚心锁ツ
    2020-12-06 19:53

    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:

    • How can you decode multiple message types with golang websockets?
    • Partly JSON unmarshal into a map in Go

提交回复
热议问题