Unstructured JSON to Golang
I really like the way Go imports json into its own data structures.
You just define a struct, annotate it to map the JSON field names to the struct field names (taking care to follow the Go convention of using Capitalised initials where the field is public).
There are also some great tools to automatically generate the struct from JSON
But where I got stuck was with JSON that is flexible and doesn’t match something I can directly make in Go.
In my case there is a structure - but it’s not 100% compatible with Go strong typing.
I have a large struct and some of the fields can be of more than one possible type.
The solution for me was Using Go’s json.RawMessage
Part of my struct looks as below
type Article struct {
Entity struct {
ID int `json:"id"`
Title string `json:"title"`
Slug string `json:"slug"`
Content string `json:"content"`
Components []struct {
Type string `json:"type"`
Data json.RawMessage `json:"data"`
} `json:"components"`
To get my struct from a file
func getArticleFromFile(filename string) Article {
jsonFile, err := os.Open(filename)
if err != nil {
panic(err)
}
articleBytes, err := io.ReadAll(jsonFile)
if err != nil {
panic(err)
}
var article Article
json.Unmarshal(articleBytes, &article)
return article
}
So here I have the whole object imported - but the variable bit is still raw - a byte array - that I can unmarshal later when I have figured out what kind of object it is.
My components array has a “type” field which tells me what kid if thing it contains - so I can use a switch statement here
Im my case I have a type called “references” which is just an array of strings and can be unmarshalled like this
for _, component := range article.Entity.Components {
switch component.Type {
case "references":
var data []string
json.Unmarshal(component.Data, &data)
Other types are more complex and I’ll need to create new structs for these.
In my case I don’t need to fully resolve the whole JSON object into a single structure - I just need to be able to parse it and use the data - having a few different objects that represent the whole thing is no problem.