Understanding how to unmarshal JSON into an interface{} is a crucial skill for Go developers. In this article, we will walk through a practical example that highlights the pitfalls and solutions associated with unmarshaling JSON into a struct with an interface{} field.
Consider the following type definitions:
type Message struct { Cmd string `json:"cmd"` Data interface{} `json:"data"` } type CreateMessage struct { Conf map[string]int `json:"conf"` Info map[string]int `json:"info"` }
Given a JSON string representing a create message, we might attempt to decode it into a Message struct:
{"cmd":"create","data":{"conf":{"a":1},"info":{"b":2}}
import "encoding/json" var data = []byte(`{"cmd":"create","data":{"conf":{"a":1},"info":{"b":2}}`) var m Message if err := json.Unmarshal(data, &m); err != nil { log.Fatal(err) }
Upon examining the unmarshaled Message struct, we notice that the Data field remains as a map[string]interface{}:
{Cmd:create Data:map[conf:map[a:1] info:map[b:2]]}
To overcome this limitation, we employ a two-pronged approach:
type Message struct { Cmd string `json:"cmd"` Data json.RawMessage } type CreateMessage struct { Conf map[string]int `json:"conf"` Info map[string]int `json:"info"` }
With these modifications, we can decode the variant data into the appropriate struct type based on the command:
func main() { var m Message if err := json.Unmarshal(data, &m); err != nil { log.Fatal(err) } switch m.Cmd { case "create": var cm CreateMessage if err := json.Unmarshal([]byte(m.Data), &cm); err != nil { log.Fatal(err) } fmt.Println(m.Cmd, cm.Conf, cm.Info) default: log.Fatal("bad command") } }
By employing this technique, we can successfully unmarshal the JSON data into the Message struct, where the Data field contains the variant CreateMessage type. Refer to the provided playground example for a complete implementation.
The above is the detailed content of How to Effectively Unmarshal JSON into an Interface{} in Go?. For more information, please follow other related articles on the PHP Chinese website!