Handling Null JSON Arrays in Go
Tags: tipsandtricks, go, json
Published: 2020-07-12 18:19:26

---
title: Handling Null JSON Arrays in Go
published: true
date: 2020-07-10 21:25:09 UTC
tags: tipsandtricks,go,json,golang
canonical_url: https://medium.com/swlh/arrays-and-json-in-go-98540f2fa74e
firstPublishedAt: 1594416309626
latestPublishedAt: 1594542531625
---

![Photo by [JESHOOTS.COM](https://unsplash.com/@jeshoots?utm_source=medium&utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral)](https://cdn-images-1.medium.com/max/10944/0*ziNdAFPl98V9thNL)

One of the most frustrating things with Go is how it handles empty arrays when encoding JSON. Rather than returning what is traditionally expected, an empty array, it instead returns null. For example, the following:

{% gist https://gist.github.com/stnguyen90/90e6c2d8f90934444e3e3f78263e8502 %}

Outputs:

```json
{"Items":null}
```

This occurs because of how the [json package](https://golang.org/pkg/encoding/json/#Marshal) handles nil slices:

> Array and slice values encode as JSON arrays, except that []byte encodes as a base64-encoded string, and a **nil slice encodes as the null JSON value**.

There are some proposals to amend the json package to handle nil slices:

- [encoding/json `nilasempty` to encode nil-slices as `[]`](https://github.com/golang/go/issues/37711)

- [encoding/json: “nonil” struct tag to marshal nil slices and maps as non-null](https://github.com/golang/go/issues/27589)

But, as of this writing, these proposals have not been accepted. As such, in order to overcome the problem of null arrays, we have to set nil slices to empty slices. See the addition of line 22 in the following:

{% gist https://gist.github.com/stnguyen90/f526bd8025746b7dc85e239270a4cff1 %}

Changes the output to:

```json
{"Items":[]}
```

However, this can become quite tedious to do everywhere there can potentially be a nil slice. Is there a better way to do this? Let’s see!

# Method 1: Custom Marshaler

According to the [Go json docs](https://golang.org/pkg/encoding/json/#Marshal):

> Marshal traverses the value v recursively. If an encountered value implements the Marshaler interface and is not a nil pointer, **Marshal calls its MarshalJSON method to produce JSON**.

So, if we implement the `Marshaler` interface:

```go
// Marshaler is the interface implemented by types that
// can marshal themselves into valid JSON.
type Marshaler interface {
    MarshalJSON() ([]byte, error)
}
```

Our `MarshalJSON()` will be called when encoding the data. See the additional `MarshalJSON()` at line 14:

{% gist https://gist.github.com/stnguyen90/6eafc320709412b9f90cda3d18c547bc %}

This would then output:

```json
{"Items":[]}
```

The `Alias` on line 15 is required to prevent an infinite loop when calling `json.Marshal()`.

# Method 2: Dynamic Initialization

Another way to handle nil slices is to use the [reflect package](https://golang.org/pkg/reflect/) to dynamically inspect every field of a struct; if it’s a nil slice, replace it with an empty slice. See `NilSliceToEmptySlice()` on line 15:

{% gist https://gist.github.com/stnguyen90/11e4504b491e6574d0fc1e83e285e675 %}

This would then output:

```json
{"Items":[]}
```

# Review

The drawback of the custom marshaler is you have to write one for every struct that has slices. Because it’s custom, though, it can target the specific field that might be a nil slice.

The dynamic initialization approach is definitely slower because every field of the struct needs to be inspected to see if it needs to be replaced. However, this approach works well if you have lots of structs with slices and few places where you call `json.Marshal()`.

Which approach would you use? Let me know in the comments below!