Skip to content

Instantly share code, notes, and snippets.

@wblakecaldwell
Last active August 29, 2015 14:13
Show Gist options
  • Save wblakecaldwell/f24a6ef7ab74c08bdec5 to your computer and use it in GitHub Desktop.
Save wblakecaldwell/f24a6ef7ab74c08bdec5 to your computer and use it in GitHub Desktop.
JSON Encoding in Go: Dealing with Sensitive Fields
//
// Golang example: Handling sensitive struct fields when JSON encoding.
//
// Blog Post: http://blakecaldwell.net/blog/2015/1/20/json-encoding-in-go-dealing-with-sensitive-fields.html
//
// Try this in the Go Playground: https://play.golang.org/p/Du5ztx6zjC
//
// Author
// ------
//
// Blake Caldwell
// http://blakecaldwell.net
// http://twitter.com/blakecaldwell
//
// Script Output
// -------------
//
// Person: {
// "FirstName": "Arthur",
// "LastName": "Dent",
// "AuthToken": "green-ones"
// }
// SafePerson: {
// "FirstName": "Arthur",
// "LastName": "Dent"
// }
// PrettySafePerson - AuthToken has value: {
// "FirstName": "Arthur",
// "LastName": "Dent",
// "AuthToken": "green-ones"
// }
// PrettySafePerson - AuthToken is empty: {
// "FirstName": "Arthur",
// "LastName": "Dent"
// }
// PublicPerson: {
// "FirstName": "Arthur",
// "LastName": "Dent"
// }
// PublicPerson with AuthToken: {
// "FirstName": "Arthur",
// "LastName": "Dent",
// "AuthToken": "green-ones"
// }
//
package main
import (
"encoding/json"
"fmt"
)
// Person struct that includes all fields in JSON
type Person struct {
FirstName string
LastName string
AuthToken string
}
// SafePerson omits AuthToken in JSON
type SafePerson struct {
FirstName string
LastName string
AuthToken string `json:"-"`
}
// PrettySafePerson omits AuthToken if it doesn't have a value
type PrettySafePerson struct {
FirstName string
LastName string
AuthToken string `json:",omitempty"`
}
// PublicPerson decorates a Person, hiding AuthToken by default
type PublicPerson struct {
*Person
AuthToken string `json:",omitempty"`
}
// IncludeAuthToken unhides the Person's AuthToken
func (p *PublicPerson) IncludeAuthToken() {
p.AuthToken = p.Person.AuthToken
}
func main() {
// Print JSON for a Person, which shows all fields
person := Person{
FirstName: "Arthur",
LastName: "Dent",
AuthToken: "green-ones",
}
printJSON("Person", person)
// Print JSON for a SafePerson, which hides AuthToken because it's always omitted
safePerson := SafePerson{
FirstName: "Arthur",
LastName: "Dent",
AuthToken: "green-ones",
}
printJSON("SafePerson", safePerson)
// Print JSON for PrettySafePerson, which hides AuthToken if it's empty
prettySafePerson := PrettySafePerson{
FirstName: "Arthur",
LastName: "Dent",
AuthToken: "green-ones",
}
printJSON("PrettySafePerson - AuthToken has value", prettySafePerson)
prettySafePerson.AuthToken = ""
printJSON("PrettySafePerson - AuthToken is empty", prettySafePerson)
// Print JSON for PublicPerson, which decorates Person, hiding AuthToken by overriding it
pe := PublicPerson{
Person: &person,
}
printJSON("PublicPerson", pe)
// Print JSON for the same PublicPerson after including AuthToken
pe.IncludeAuthToken()
printJSON("PublicPerson with AuthToken", pe)
}
func printJSON(name string, thing interface{}) {
jsonBytes, err := json.MarshalIndent(thing, "", " ")
if err != nil {
fmt.Printf("ERROR: %s\n", err)
return
}
fmt.Printf("%s: %s\n", name, string(jsonBytes))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment