Unmarshaling JSON with Self-Referential Struct Elements
Consider the following JSON string with a nested structure:
[{ "db": { "url": "mongodb://localhost", "port": "27000", "uname": "", "pass": "", "authdb": "", "replicas": [ { "rs01": { "url":"mongodb://localhost", "port": "27001", "uname": "", "pass": "", "authdb": "" } }, { "rs02": { "url":"mongodb://localhost", "port": "27002", "uname": "", "pass": "", "authdb": "" } } ] } }]
To represent this JSON in a Go struct, we define the following struct:
type DBS struct { URL string `json:"url"` Port string `json:"port"` Uname string `json:"uname"` Pass string `json:"pass"` Authdb string `json:"authdb"` Replicas []DBS `json:"replicas"` }
However, attempting to unmarshal the JSON string into a slice of this struct results in an empty slice.
The issue lies in the fact that the JSON input is not a slice of DBS structs. Instead, it contains another JSON object wrapper, and a value of DBS belongs to the "db" property. Additionally, the "replicas" property contains a JSON array with objects holding varying keys, which can also be represented by DBS structs.
To fully model this JSON, we need a dynamic type, such as a map. The type we require is []map[string]DBS, which represents a slice of maps. The map key can model any property name, and the value is a JSON object modeled by the DBS struct.
The following example demonstrates how to fully parse the JSON input using this type:
import ( "encoding/json" "fmt" ) type DBS struct { URL string `json:"url"` Port string `json:"port"` Uname string `json:"uname"` Pass string `json:"pass"` Authdb string `json:"authdb"` Replicas []map[string]DBS `json:"replicas"` } func main() { var dbs []map[string]DBS if err := json.Unmarshal([]byte(src), &dbs); err != nil { panic(err) } fmt.Printf("%+v", dbs) }
Output:
[map[db:{URL:mongodb://localhost Port:27000 Uname: Pass: Authdb: Replicas:[map[rs01:{URL:mongodb://localhost Port:27001 Uname: Pass: Authdb: Replicas:[]}] map[rs02:{URL:mongodb://localhost Port:27002 Uname: Pass: Authdb: Replicas:[]}]]}]]
Note that the first level is always "db", which can be further modeled, and we can switch to pointers for improved readability.
By understanding the nesting and structure of the JSON input, we can effectively unmarshal it into a custom struct that accurately represents the data.
The above is the detailed content of How to Unmarshal Complex, Self-Referential JSON in Go?. For more information, please follow other related articles on the PHP Chinese website!