Recently I came across this gotcha in Golang while I was writing a plugin for Gauge that generates JSON report.

Let me start with an example. Say I want to generate JSON by marshalling a type as follows:

type Person struct {
	Friends []string // Field should be exported
}

In this Person entity, the field Friends contains a list of friends represented as a slice of strings. This field could be returned as null from another service(Does that mean he has no friends? Ah no idea who this person is!).

I wrote the below code which marshals the input and was surprized to look at the output.

var f1 []string
json1, _ := json.Marshal(Person{f1})
fmt.Printf("%s\n", json1)

Output :

{"Friends":null}

This marks the field Friends as null whereas I was expecting it to have empty slice in JSON.

The reason for this was the way I had initialized the slice. When I initialize the f1 as var f1 []string, it is a nil pointer and when marshalled, it gives you null instead of [].

var x interface{}
x = 10

To fix this, I had to initialize the variable as f2 := make([]string, 0) and this gives you output as empty slice instead of null.

f2 := make([]string, 0)
json2, _ := json.Marshal(Person{f2})
fmt.Printf("%s\n", json2)

Output :

{"Friends":[]}

The same example can be seen on the Go playground here. Full program for reference:

package main

import (
	"encoding/json"
	"fmt"
)

type Person struct {
	Friends []string
}

func main() {
	var f1 []string
	f2 := make([]string, 0)

	json1, _ := json.Marshal(Person{f1})
	json2, _ := json.Marshal(Person{f2})

	fmt.Printf("%s\n", json1)
	fmt.Printf("%s\n", json2)
}