JSON Encoding in Go: Dealing with Sensitive Fields
JSON marshalling in Go is pretty straight-forward, but sometimes your structs contain sensitive information that you’d like to keep out of your public JSON API. Fortunately, there are a few good solutions that don’t require you to manually copy every field from one struct type to another.
Let’s start with our basic Person
struct:
The simplest way to prevent exposing AuthToken
via JSON is with the json:"-"
tag, which tells the json to always ignore this field. Let’s call this SafePerson
, because you never have to worry about exposing AuthToken via JSON:
This works really well, until you need to include the field some of the time, like when showing someone their own record. In that case, you could try the json:",omitempty"
tag, which only includes the field if it has a value. It’d be up to you to clear it out when it doesn’t belong in the JSON. This is PrettySafePerson
, because it’s safe if you’re careful:
This is great, but… here’s the thing. That one time you forget to clear an AuthToken
for someone other than the Person that it represents might give you quite the headache. I’d rather err on the side of safety, where forgetting something means not showing data that I meant to.
Here’s where we can take advantage of Go’s type embedding. By embedding a Person
inside another struct, we borrow all of the Person
’s fields, and can override some without affecting the Person
. We’ll build our API with this pattern, which always omit sensitive fields unless told otherwise.
PublicPerson
’s AuthToken
field overrides the embedded Person.AuthToken
, and because of the json:",omitempty"
key, it’ll be hidden from JSON unless you set it. Person.AuthToken
still has the original value, you can include it in the JSON by calling IncludeAuthToken()
.
Try it out in the Go Playground