Use Anonymous Structs For JSON Marshalling in Go

Go is a language built for the web. The Go standard library comes with everything we need to stand up a production web server. Today we are going to explore marshaling JSON using anonymous structs. Anonymous structs can help keep API handlers clean and simple.

What Is A Struct?

Go’s structs are typed collections of fields. They’re useful for grouping data together to form records.
https://gobyexample.com/structs

Structs don’t have behavior, just data. For web developers, it can be helpful (though an oversimplification) to think of most structs as just JSON data.

We can declare a struct:

type car struct {
        make    string
        model   string
        mileage int
}

And we can create and instance of it:

newCar := car{
        make:    "Ford",
        model:   "taurus",
        mileage: 200000,
}

What Makes a Struct Anonymous?

An anonymous struct is declared in the same statement that initializes an instance of it:

newCar := struct {
        make    string
        model   string
        mileage int
}{
        make:    "Ford",
        model:   "Taurus",
        mileage: 200000,
}

Anonymous structs are great for unmarshalling JSON data in HTTP handlers. If a struct is only meant to be used once, then it makes sense to declare it in such a way that developers down the road won’t be tempted to use it again:

func createCarHandler(w http.ResponseWriter, req *http.Request) {
        defer req.Body.Close()
        decoder := json.NewDecoder(req.Body)
        newCar := struct {
                Make    string `json:"make"`
                Model   string `json:"model"`
                Mileage int    `json:"mileage"`
        }{}
        err := decoder.Decode(&newCar)
        if err != nil {
                log.Println(err)
                return
        }
        makeCar(newCar.Make, newCar.Model, newCar.Mileage)
        return
}

Don’t Use Map[string]interface{}

Instead of declaring a quick anonymous struct for JSON unmarshalling, I’ve often seen map[string]interface{} used. This is bad in most scenarios because:

  1. No type checking – if the client sends “model” as a boolean, which was supposed to be a string, then unmarshalling into a map won’t catch the error
  2. Vague – After unmarshalling the data, we must use runtime checks for existence. If those checks aren’t thorough, it can lead to nil pointer dereference panic exceptions being thrown.
  3. Verbose – Digging into the struct isn’t as simple as accessing a named field as in “newCar.model”. Instead, its something like:
func createCarHandler(w http.ResponseWriter, req *http.Request) {
        myMap := map[string]interface{}{}
        decoder := json.NewDecoder(req.Body)
        err := decoder.Decode(&myMap)
        if err != nil {
                log.Println(err)
                return
        }
        model, ok := myMap["model"]
        if !ok {
                fmt.Println("field doesn't exist")
                return
        }
        modelString, ok := model.(string)
        if !ok {
                fmt.Println("model is not a string")
        }
        // do something with model field
}

Anonymous structs can clean up your API handlers if used properly. The strong typing they offer while still being a “one-off” solution is a powerful tool.

Thanks For Reading

Hit me up on twitter @wagslane if you have any questions or comments.

Follow me on Dev.to: wagslane

The post Use Anonymous Structs For JSON Marshalling in Go appeared first on Qvault.



source https://qvault.io/2020/04/21/use-anonymous-structs-for-json-marshalling-in-go/

Comments

Popular posts from this blog

Why is Exclusive Or (XOR) Important in Cryptography?

Base64 vs Base58 Encoding

(Very) Basic Intro to Hash Functions (SHA-256, MD-5, etc)