How to Convert a Go Object to or from JSON

This post will describe how to convert from a Go struct into a JSON string, and back again. There is a built in package, encoding/json, that does pretty much all the work for you – for a detailed description of it, click here. Otherwise, read on for some quick examples and some tips.

The Basics

Within the json package, the Marshal function takes care of converting an object into a JSON string, and it works out of the box. You can use it on pretty much any object you want. For example:

package main

import (
	"encoding/json"
	"fmt"
)

type Person struct {
	Name          string
	Age           int
	FavoriteWords []string
}

func main() {
	newPerson := Person{
		Name:          "John",
		Age:           22,
		FavoriteWords: []string{"elephant", "helicopter"},
	}

	str, err := json.Marshal(newPerson)

	if err != nil {
		fmt.Printf("error: %v", err)
		return
	}

	fmt.Println(string(str))
}

(Playground)

The output:

{"Name":"John","Age":22,"FavoriteWords":["elephant","helicopter"]}
Converting Back Again

Converting back again is just as easy, provided the input JSON string contains the required keys to map to the struct. The output above can be converted back as follows:

package main

import (
	"encoding/json"
	"fmt"
)

type Person struct {
	Name          string
	Age           int
	FavoriteWords []string
}

func main() {
	inputJSON := "{\"Name\":\"John\",\"Age\":22,\"FavoriteWords\":[\"elephant\",\"helicopter\"]}"

	var newPerson Person

	err := json.Unmarshal([]byte(inputJSON), &newPerson)

	if err != nil {
		fmt.Printf("error: %v", err)
		return
	}

	fmt.Printf("%+v", newPerson)
}

(Playground)

The resulting output:

{Name:John Age:22 FavoriteWords:[elephant helicopter]}

There are, of course, a number of additional features, and things to look out for, discussed below.

Note 1 – Properties must be accessible outside your package.

For the encoding/json package to work its magic, it needs to be able to access the properties of the object it is marshaling to JSON. If you’re new to Go, that means the property name when you define the struct needs to start with a capital letter. If you change the Age property to age in the above, you’ll see the following output:

{"Name":"John","FavoriteWords":["elephant","helicopter"]}

(Playground)

Age is now ignored in the marshaling process as the json/encoding package can’t see it.

Note 2 – Change the JSON key in the output by using a struct field tag.

Go allows fields of a struct to be decorated with a tag, these can be read by packages operating on the struct and change the way they are treated. If your json is following a specification where keys are all camel case, starting with a lower case letter, you’ll want the marshaled string to meet this specification. This is done by adding a field tag.

In the above example, the Person struct could have been defined like this:

type Person struct {
	Name          string   `json:"name"`
	Age           int      `json:"age"`
	FavoriteWords []string `json:"favoriteWords"`
}

(Playground)

The resulting output would then be:

{"name":"John","age":22,"favoriteWords":["elephant","helicopter"]}

Unmarshaling would obviously require the input keys to also be camelCase.

Note 3 – Omit fields from the output by using a “-” as the key name.

If you need to omit a publicly accessible field, then set the output key to be “-“. This will be ignored by the encoding/json package. For example:

type Person struct {
	Name          string   `json:"name"`
	Age           int      `json:"age"`
	FavoriteWords []string `json:"-"`
}

(Playground)

Would print:

{"name":"John","age":22}
Note 4 – Omit empty fields with the omitempty tag.

If you want to omit a field but if it is empty, this can be done by including an omitempty tag, this must be the second json tag. The person object could be defined like so:

type Person struct {
	Name          string   `json:"name"`
	Age           int      `json:"age"`
	FavoriteWords []string `json:"favoriteWords,omitempty"`
}

(Playground)

If there were no favorite words, the output would be:

{"name":"John","age":22}
Conclusion

With great power comes great responsibility.

Leave a Reply

Your email address will not be published. Required fields are marked *