Asset 31Asset 32
Navigate back to the homepage

Handling JSON in Go

Sebastian Ojeda
September 18th, 2019 · 1 min read

Go was built with the modern web in mind. Native concurrency as well as packages like “net/http” for client and server interactions are just the tip of the iceburg of all the goodness that’s packed into Go. Of course, if you plan on developing anything for the web, you will without a doubt come across JSON. While encoding and decoding JSON in other languages such as Java can be a pain, Go’s “encoding/json” package provides all you need to handle those pesky JSON strings.

Marshalling JSON

First thing’s first. You want to encode a JSON string. For that, we use the Marshal function.

1func Marshal(v interface{}) ([]byte, error)

For example, to encode a User we can do

1// User Don't forget to annotate exported values
2type User struct {
3 Username string
4 Password string
7myUser := User{
8 Username: "Sebastian",
9 Password: "Its@S3cret",
12b, err := json.Marshal(myUser)

If all goes right, then you should see that

1b == []byte(`{"Username": "Sebastian","Password":"Its@S3cret"}`)

However, in the real world, the field names in JSON often do not match up with your declared field names. In this case, you can trail the struct field declarations with a string literal (called tags) in the following format

1type User struct {
2 Username string `json:"username"`
3 Password string `json:"password"`

This would produce a JSON string that looks like this:

1{"username": "Sebastian","password":"Its@S3cret"}

Additionally, there are a few other options other than renaming the field:

1// Use 'omitempty' if you would like to omit the field when empty
2Username string `json:"username,omitempty"`
4// Use 'string' to force the value to be encoded as a JSON string
5Age int `json:"age,string"`
7// Use '-' to ignore the field completly
8Hidden string `json:"-"`

Of course, you can choose to keep the original field name and still use one of these options. Simply include a comma before the option.

1// Keep my field name as 'Password', but omit it when empty
2Password string `json:",omitempty"`

If you would like to make your output look a little prettier, you can use the MarshalIndent function

1func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error)

which will add a prefix and an indent before each new JSON element. So now you know how to encode JSON, but what about decoding?


Decoding is done in a similar fashion, using the Unmarshal function.

1func Unmarshal(data []byte, v interface{}) error

In this case, we simply want to work the other way around. Given

1b := []byte(`{"username":"Meredith","password":"notsecure"}`)

you can decode with the following

1var myUser User
3err := json.Unmarshal(b, &myUser)

and now myUser represents the decoded value b. Hooray!

⚠️ Unmarshal will only decode fields that are valid for the target type. Invalid fields are ignored.

Additional knowledge

The types that Go associates JSON with are as follows:

  • booleans are bool
  • strings are string
  • numbers are float64
  • null is nil

If you would like to check the validity of a JSON string, you can use Valid

1func Valid(data []byte) bool

Overall, there is some really nice functionality built in to Go which makes life that much easier. To learn more about this package, I encourage you to read the official package docs.

More articles from Fullstack Go

The ,ok idiom

Go encourages idiomatic code by design. If you've ever spent some time looking at Go source code, you've probably noticed this interesting pattern.

September 16th, 2019 · 1 min read

Go Runtime Environment Variables

Ever wondered what the heck all the Go runtime environment variables meant? Not anymore.

October 27th, 2019 · 3 min read
© 2019 Fullstack Go
Link to $ to $