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
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.
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