Unmarshal JSON in go with different types in a list

go, json, unmarshalling

Solution

One option would be to unmarshal the top level thing into a slice of `json.RawMessage` initially.

Then loop through the members, and look at the first character of each one. If it is an object, unmarshal that into your `InfoMap` header struct, and if it is an array, unmarshal it into a slice of the `Code` struct.

Or if it is predictable enough, just unmarshal the first member to the one struct and the second to a slice.

I made a playground example of this approach.

type Response struct {
    ID        int               `json:"id"`
    RawResult []json.RawMessage `json:"result"`
    Header    *Header           `json:"-"`
    Values    []*Value          `json:"-"`
}

type Header struct {
    Bundled bool   `json:"bundled"`
    Type    string `json:"type"`
}

type Value struct {
    Name  string `json:"name"`
    Value string `json:"value"`
}

func main() {
    //error checks ommitted
    resp := &Response{}
    json.Unmarshal(rawJ, resp)
    resp.Header = &Header{}
    json.Unmarshal(resp.RawResult[0], resp.Header)
    resp.Values = []*Value{}
    json.Unmarshal(resp.RawResult[1], &resp.Values)
}

Problem

I have trouble unmarschaling a JSON contruct: ``` { "id": 10, "result": [ { "bundled": true, "type": "RM-J1100" }, [ { "name": "PowerOff", "value": "AAAAAQAAAAEAAAAvAw==" }, { "name": "Input", "value": "AAAAAQAAAAEAAAAlAw==" } ] ] } ``` I actually need the second slice item from the result. My current attempt is ``` type Codes struct { Id int32 `json:"id"` Result []interface{} `json:"result"` } type ResultList struct { Info InfoMap Codes []Code } type InfoMap struct { Bundled bool `json:"bundled"` Type string `json:"type"` } type Code struct { Name string `json:"name"` Value string `json:"value"` } ``` the output is like: ``` {10 {{false } []}} ``` but I also tried to use this: ``` type Codes struct { Id int32 `json:"id"` Result []interface{} `json:"result"` } ``` the output is okay: ``` {10 [map[type:RM-J1100 bundled:true] [map[name:PowerOff value:AAAAAQAAAAEAAAAvAw==] map[name:Input value:AAAAAQAAAAEAAAAlAw==]]]} ``` I can also reference the Result[1] index: ``` [map[name:PowerOff value:AAAAAQAAAAEAAAAvAw==] map[name:Input value:AAAAAQAAAAEAAAAlAw==]] ``` But I fail to convert the interface type to any other Type which would match. Can anybody tell me how to do interface conversion. And what approach would be the "best".

Original source